为何要用combineReducers,由于这样能够分离相应的逻辑redux
Reducer是管理state的一个控件,它要作的事情就是当state没有的时候,返回initalState,有的时候根据action来状态变化,这里注意它是一个纯函数,也就是它不改变传入的state
{...state, ...newState}函数
当咱们的reducer去处理不少action的时候,咱们能够根据key把它拆分开,是的逻辑更加清晰code
import { VisibilityFilters, ADD_TODO, TOGGLE_TODO } from './actions' ... function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return Object.assign({}, state, { visibilityFilter: action.filter }) case ADD_TODO: return Object.assign({}, state, { todos: [ ...state.todos, { text: action.text, completed: false } ] }) case TOGGLE_TODO: return Object.assign({}, state, { todos: state.todos.map((todo, index) => { if (index === action.index) { return Object.assign({}, todo, { completed: !todo.completed }) } return todo }) }) default: return state } }
由于todos跟visibilityFilter是分开更新的,因此其实咱们能够把它们分开来it
function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [ ...state, { text: action.text, completed: false } ] case TOGGLE_TODO: return state.map((todo, index) => { if (index === action.index) { return Object.assign({}, todo, { completed: !todo.completed }) } return todo }) default: return state } } function visibilityFilter(state = SHOW_ALL, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return action.filter default: return state } } function todoApp(state = {}, action) { return { visibilityFilter: visibilityFilter(state.visibilityFilter, action), todos: todos(state.todos, action) } }
这样每一个reducer只负责本身那一块的状态更新,combindReducers作了上面todoApp作的事情,就是返回一个大的function 接受state,action,而后根据key用不一样的reducerio
import { combineReducers } from 'redux' const todoApp = combineReducers({ visibilityFilter, todos }) export default todoApp
const reducer = combineReducers({ a: doSomethingWithA, b: processB, c: c }) function reducer(state = {}, action) { return { a: doSomethingWithA(state.a, action), b: processB(state.b, action), c: c(state.c, action) } }
注意:combinedReducer的key跟state的key同样
知道了需求以后咱们来写一个本身的combindReducer吧function
function combindReducer(reducers) { // 第一个只是先过滤一遍 把非function的reducer过滤掉 const reducerKeys = Object.keys(reducers) const finalReducers = {} reducerKeys.forEach((key) => { if(typeof reducers[key] === 'function') { finalReducers[key] = reducers[key] } }) const finalReducersKeys = Object.keys(finalReducers) // 第二步比较重要 就是将全部reducer合在一块儿 // 根据key调用每一个reducer,将他们的值合并在一块儿 let hasChange = false; const nextState = {}; return function combind(state={}, action) { finalReducersKeys.forEach((key) => { const previousValue = state[key]; const nextValue = reducers[key](previousValue, action); nextState[key] = nextValue; hasChange = hasChange || previousValue !== nextValue }) return hasChange ? nextState : state; } }