首先,这里默认读着已经熟练理解Redux的使用了,如果还不是很熟练,请参照Redux,这个是我读过最好的理解Redux的文章。
首先看一下函数的使用方法,要理解最终函数的目的就是把两个Reducer变成一个Reducer导出:
function card(state, action) {
switch (action.type) {
case 'CHANGE_NAME':
return {
name: action.name, // 使用action携带的新name
picture: state.card.picture // 不需要修改,使用旧state的值
}
default:
return state // 没有匹配的action type,返回原来的state
}
}
function dialog(state, action) {
switch (action.type) {
case 'SHOW_DIALOG':
return {
status: true
}
case 'CLOSE_DIALOG':
return {
status: false
}
default:
return state // 没有匹配的action type,返回原来的state
}
}
export default combineReducers({
card,
dialog
})
combineReducers接受了多个reducer作为参数,
其实参数都是以键值对的形式传入的,只是她们同名了可以简写成这样,如果不想不同名,就要用冒号的形式来写了,比如card:cardReducer,源码中会解释这样写的原因。
export default function combineReducers(reducers) {
const reducerKeys = Object.keys(reducers) //遍历传入参数的Key[card,dialog]
const finalReducers = {} //最终要得到的结果
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') { //reducers[card,dialog],也就是上面自己定义的函数
finalReducers[key] = reducers[key] //如果是函数,就放入到返回结果中,key保持不变。这里只是做了过滤
}
}
const finalReducerKeys = Object.keys(finalReducers) //得到新的key
let unexpectedKeyCache
if (process.env.NODE_ENV !== 'production') {
unexpectedKeyCache = {}
}
let shapeAssertionError
try {
assertReducerShape(finalReducers) //判断reducer是否格式正确,该函数作用为当传入的type不存在时,是否会返回默认值。
} catch (e) {
shapeAssertionError = e
}
return function combination(state = {}, action) {
if (shapeAssertionError) {
throw shapeAssertionError //如果存在不返回默认值的Reducer,抛出异常。
}
if (process.env.NODE_ENV !== 'production') { //发出警告,不影响程序执行
const warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache)
if (warningMessage) {
warning(warningMessage)
}
}
let hasChanged = false //重点在这下面,是否发生了改变。
const nextState = {} //要返回的下一个状态。
for (let i = 0; i < finalReducerKeys.length; i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key] //根据key得到reducer
const previousStateForKey = state[key] //这里重点介绍一下,使用该函数要求,每个reducer的key值要和当前操作的state的参数同名,比如我传入card:cardReducer 那么我的state操作的参数就必须是state.card才行,这里印证了答案。
const nextStateForKey = reducer(previousStateForKey, action)
if (typeof nextStateForKey === 'undefined') {
const errorMessage = getUndefinedStateErrorMessage(key, action)
throw new Error(errorMessage) //这里再次验证了是否会返回undefined,即是否有默认值存在,可见框架级别的内容很严谨
}
nextState[key] = nextStateForKey //执行reducer之后的结果
hasChanged = hasChanged || nextStateForKey !== previousStateForKey //每次执行之后的结果,再综合上一次得到的结果 hasChanged,得到最终是否state发生了变化
}
return hasChanged ? nextState : state //如果发生了变化就要返回新的state->nextState
}
}