combineReducer
对于将多个reducer合并为一个的做法,redux为我们提供了一个方便的API叫combineReducer
,同样,为了搞懂它到底是怎么运作的,我们可以尝试实现它。
在之前的例子里,我们注意到最后返回的reducer的key与子reducer同名,所以函数内部过程应该是:
- 向combineReducer传入一个对象,假设我们有子reducer A,B, 那么我们这样传入: combineReducer({A, B}) ,它的对等形式就是: combineReducer({A: A, B: B}),这是ES6的语法糖 - Destructing Assignment.
- 获取key数组
- 以这个key数组为数据,获取一个合并后的
reducer
函数
/**
* combineReducer => merge all reducer function into one
* @param [Object] reducers object, { reducerVaribale, ... }
* @return [function] mixed reducer function
*/
const combineReducer = (reducers) => {
return (state = {}, action) => { // return a reduce function
return Object.keys(reducers).reduce(
(nextState, key) => { // When gave an initial value(here is {}), nextState will be {}
nextState[key] = reducers[key](state[key], action)
// This is actually very similar to 'todos: todos(state.todos, action)' in todos reducer
return nextState
},
{} //initial value => offered a container for mixed state
)
}
}
OK,我们把其中最麻烦的一部分拿出来分析:
Object.keys(reducers).reduce(
(nextState, key) => {
nextState[key] = reducers[key](state[key], action)
return nextState
},
{} //initial value => offered a container for mixed state
)
我们假设{ReducerA, ReducerB}是参数reducers:
Object.keys(reducers)
=>['ReducerA', 'ReducerB']
['ReducerA', 'ReducerB'].reduce()
- 我们把里面的函数提取出来:
function (accumulator, currentValue) { }
- 如果我们不给定reduce函数一个
initialValue
, 那么初始状态下accumulator
会是第一个key
,显然,我们的操作对象不是key
,而是一个对象,这个对象将包含所有的state
. - 给定
initialValue
:{}
,接上面第三步,函数体:accumulator[currentValue] = reducers[currentValue](state[currentValue], action)
- 手动跑reduce结果:
- Initial State 对应关系:
accumulator = {}
,currentValue = 'ReducerA'
{}['ReducerA'] = ReducerA(state['ReducerA],action)
此时state['ReducerA]
为undefined
,前面解释过,ReducerA
自带默认state
,会正常返回值.
- Second State 对应关系:
accumulator = { 'ReducerA' : ReducerA返回的state }
,currentValue = 'ReducerB
- Initial State 对应关系:
现在清晰了吗? 最后的返回结果便会是{ 'ReducerA' : ReducerA返回的state, 'ReducerB' : ReducerB返回的state }
测试一下我们的函数是否可用:
It works !