爲何要用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; } }