Redux源码阅读(二)——combineReducers
调试项目
【Redux源码阅读(二)——combineReducers】仓库:https://github.com/reduxjs/react-redux
项目:examples/todos
combineReducers
调试代码
import { combineReducers } from 'redux'
import todos from './todos'
import visibilityFilter from './visibilityFilter'export default combineReducers({
todos,
visibilityFilter
})
源码
export default function combineReducers(reducers: ReducersMapObject) {
const reducerKeys = Object.keys(reducers)
const finalReducers: ReducersMapObject = {}
for (let i = 0;
i < reducerKeys.length;
i++) {
const key = reducerKeys[i]if (process.env.NODE_ENV !== 'production') {
if (typeof reducers[key] === 'undefined') {
warning(`No reducer provided for key "${key}"`)
}
}if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key]
}
}
const finalReducerKeys = Object.keys(finalReducers)// This is used to make sure we don't warn about the same
// keys multiple times.
let unexpectedKeyCache: { [key: string]: true }
if (process.env.NODE_ENV !== 'production') {
unexpectedKeyCache = {}
}let shapeAssertionError: Error
try {
assertReducerShape(finalReducers)
} catch (e) {
shapeAssertionError = e
}return function combination(
state: StateFromReducersMapObject = {},
action: AnyAction
) {
if (shapeAssertionError) {
throw shapeAssertionError
}if (process.env.NODE_ENV !== 'production') {
const warningMessage = getUnexpectedStateShapeWarningMessage(
state,
finalReducers,
action,
unexpectedKeyCache
)
if (warningMessage) {
warning(warningMessage)
}
}let hasChanged = false
const nextState: StateFromReducersMapObject = {}
for (let i = 0;
i < finalReducerKeys.length;
i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
const previousStateForKey = state[key]
const nextStateForKey = reducer(previousStateForKey, action)
if (typeof nextStateForKey === 'undefined') {
const errorMessage = getUndefinedStateErrorMessage(key, action)
throw new Error(errorMessage)
}
nextState[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
hasChanged =
hasChanged || finalReducerKeys.length !== Object.keys(state).length
return hasChanged ? nextState : state
}
}
调用combineReducers
-
combineReducers
接收一个对象reducers,然后遍历reducers,筛出value为function的放入finalReducers
;
finalReducers
的结构在这个例子里是这样的
{
todos:function(){…},
visibilityFilter:function(){…}
}
- 使用
assertReducerShape
来校验,调用reducer时有没有传出默认的state; -
return combination
函数作为新的reducer
combination
函数- 调用场景有主动调用和初始化调用。上篇说到,最开始的时候redux将会调用一次reducer去获取state的初始值;
- 使用传入的action,依次调用
finalReducers
对象里的方法。
也就是说,如果我们刚开始传入的todos、 visibilityFilter这两个reducers这里面有相同的action.type,那么逻辑将会依次被触发。
var _key = finalReducerKeys[_i];
var reducer = finalReducers[_key];
var previousStateForKey = state[_key];
var nextStateForKey = reducer(previousStateForKey, action);
值得注意的是,在调用的时候传入各个reducer的state仅限于state[key],而不是整个state
- 设定调用之后的state
nextState[_key] = nextStateForKey;
可以从这里得知,每个传入的reducer都对应同名的state的key,他们return的新state只会对state[key]的value做更新
- 执行结果
{
todos: []
visibilityFilter: "SHOW_ALL"
}
推荐阅读
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- Ⅴ爱阅读,亲子互动——打卡第178天
- 上班后阅读开始变成一件奢侈的事
- 历史教学书籍
- 绘本讲师训练营【24期】14/21阅读原创《小黑鱼》
- 21天|21天|M&M《见识》04
- 绘本讲师训练营7期9/21阅读原创《蜗牛屋|绘本讲师训练营7期9/21阅读原创《蜗牛屋 》
- 桂妃研读社|桂妃研读社|D124|如何有效阅读一本书 Day1
- Android事件传递源码分析
- 4.23世界阅读日,樊登读书狂欢放送,听书中成长