拆分 Reducer 逻辑
对于任何有意义的应用程序,将所有更新逻辑放在单个 reducer 函数中很快就会变得难以维护。虽然没有关于函数长度的单一规则,但普遍认为函数应该相对较短,理想情况下只做一件特定的事情。因此,良好的编程实践是将非常长或做很多不同事情的代码片段分解成更小的、更容易理解的片段。
由于 Redux reducer 仅仅是一个函数,因此相同的概念也适用。您可以将一些 reducer 逻辑拆分到另一个函数中,并在父函数中调用该新函数。
这些新函数通常会分为以下三类
- 包含一些可重用逻辑块的小型实用函数,这些逻辑块在多个地方需要(可能与特定业务逻辑无关)
- 处理特定更新情况的函数,这些函数通常需要除典型
(state, action)
对之外的其他参数 - 处理给定状态切片所有更新的函数。这些函数通常具有典型的
(state, action)
参数签名
为了清晰起见,这些术语将用于区分不同类型的函数和不同的用例
- reducer:任何具有
(state, action) -> newState
签名的函数(即,任何可以作为Array.prototype.reduce
的参数使用的函数) - 根 reducer:实际作为第一个参数传递给
createStore
的 reducer 函数。这是 reducer 逻辑中唯一必须具有(state, action) -> newState
签名的部分。 - 切片 reducer:用于处理状态树中特定切片的更新的 reducer,通常通过将其传递给
combineReducers
来完成 - 情况函数:用于处理特定操作的更新逻辑的函数。这实际上可能是一个 reducer 函数,或者可能需要其他参数才能正常工作。
- 高阶 reducer:一个函数,它以 reducer 函数作为参数,并/或返回一个新的 reducer 函数作为结果(例如
combineReducers
或redux-undo
)
在各种讨论中,术语“子 reducer”也被用来指代任何不是根 reducer 的函数,尽管这个术语并不十分精确。有些人可能还会将某些函数称为“业务逻辑”(与应用程序特定行为相关的函数)或“实用函数”(不是应用程序特定的通用函数)。
将一个复杂的过程分解成更小、更容易理解的部分通常用术语函数分解来描述。这个术语和概念可以泛化地应用于任何代码。然而,在 Redux 中,使用方法 #3 来构建 reducer 逻辑非常常见,其中更新逻辑被委托给基于状态切片的其他函数。Redux 将这个概念称为reducer 组合,它是迄今为止构建 reducer 逻辑最广泛使用的方法。事实上,它非常常见,以至于 Redux 包含一个名为 combineReducers()
的实用函数,它专门抽象了基于状态切片将工作委托给其他 reducer 函数的过程。但是,重要的是要注意,它不是唯一可以使用的模式。事实上,完全有可能对所有三种方法都使用将逻辑拆分成函数,通常也是一个好主意。在 重构 Reducers 部分展示了一些实际示例。