前言
使用 React + Redux 构建大型项目时,通常会采用分模块开发,而每个模块也会被拆做许多的单页。在单个模块中,我们需要通过分割 reducer 的形式来管理 状态,然后通过 combineReducers()
来合并这些 reducer,再通过 createStore()
创建 store
。示例代码,请直接访问文档:Using combineReducers。
单个模块中的多个页面,共享一个 store
,不同的单页可以通过 store.getState()
的形式来获取到整个 store
,然后通过 store
访问不同页面对应的 reducer
。
在跨页面中通过 store
使用其它页面的 reducer
时,我们需要了解 combineReducers()
是起什么作用?怎么作用?
reducer
以及 combineReducers()
简单讲,combineReducers()
把多个 reducer
函数合并成一个,并返回一个新的 reducer
函数。
原始 reducer
要点:
reducer
描述一个状态模型(State Shape)。在Redux
下,应用的状态存储在一个对象类型的数据结构中。尽管你可以在运行过程中在这个对象中添加其他数据,但是最好在写代码之前设计好这个状态模型、以更加直观。reducer
处理 Action(Handling Actions)。总体的规则就是(previousState, action) => newState
,一个Action
触发,根据这个 Action 的类型进行相应的操作(请求数据、处理数据等),然后对previousState
进行修改,并返回一个新的状态newState
。原文的描述更佳直观:“Given the same arguments, it should calculate the next state and return it. No surprises. No side effects. No API calls. No mutations. Just a calculation.”
在项目中,常常要处理很多的 Action,同时 reducer
中的 State 也会变得很大,这时候就需要对 Action 和 reducer
进行分割。对于 reducer
进行分割后,我们常常需要 combineReducers()
合并成一个新的 reducer
。
combineReducers()
不是必须的。你可以选择不使用。而如果使用combineReducers()
时,reducer
的写法要遵循一定的规则,详见:combineReducers(reducers)。- 每个 diapatch 的
Action
会调用combineReducers(REDUCERS)
中所有的REDUCERS
进行处理,一个 Action 会被每个REDUCER
都处理一遍。 combineReducers()
可以多层次地组合。例如:ABC = combineReducers(A, b, C)
,然后ABCDEF = combineReducers(ABC, DEF)
。
combineReducers()
使用注意点:
-
在 ES6 中,reducer 函数为
(state = initialState, action = {}) => {}
,记得在 switch 语句 default 中返回return state;
而不是return initialState;
,否者在跨页面跳转时上一个组件的 reducer 会变为 。 假设有 reducerA、reducerB 通过combineReducers()
合并到一块,成为 BIGREDUCER(我自己命名的)。我们从 reducerA 对应的组件 A 跳转到 reducerB 对应的组件 B 时,这个BIGREDUCER
中 reducerA 的状态会变成 initialState。因为每个 Action 都会经过BIGREDUCER
中的每一个子 reducer(包括 reducerA 和 reducerB),这时候,这个 Action 是由 B 组件发出的,而在 reducerA 的 switch 中匹配不到这个 case,执行了return initialState;
,于是就出现了 reducerA 的 state 在切换到 B 组件的时候被重新初始化为 initialState 的情况。 -
注意
Action.type
的命名,一个 Action 可能会被多个reducer
匹配到。比如:一个Action.type
为 ‘QUERY_DATA’ 的 Action 由 A 组件发出,本来应该只有 A 组件对应的 reducerA 来处理,但是 reducerB 中也匹配到了,这是 reducerB 组件也会处理一次,造成数据串改。
finished on January 12, 2017 Thursday