咱們知道對於一個app, store應該是惟一,集中用reducer管理的,那麼當app中有多個頁面,每一個頁面有多個組件時,就應該有多個reducer來管理。 當我某個組件dispatch出去一個action(動做)時,store接收到action,應該交給誰來管理呢?這裏咱們暫時沒法使store根據不一樣的action來交由相應的reducer處理。
combineReducer函數將多個不一樣的reducer整合在一塊兒,而後返回一個整合後的reducer, 也就是一個函數;函數內部經過分治的方式處理不一樣的action;
注意combineReducer函數仍然屬於reduxde一部分, 因此咱們只須要在上一節的代碼中添加便可。redux
let combineReducer = (reducersObj){
// reducerObj是一個由全部所需reducer組成的對象
return (state={}, action={ type: Symbol() })=>{
// 返回值其實就是一個rootReducer, 因此參數是state, action
// 注意這個rootReducer其實就是在建立store的時候傳入的reducer.
// 上一節中,建立store的時候須要先調用一下reducer(), 以獲得state的默認狀態值;此時至關於調用rootReducer({}, {type; Symbol()})
// 因此這裏給action設置了一個默認值, 注意這裏使用了Symbol這樣會是action.type沒法匹配到用戶定義任何的actionTypes
// rootReducer會返回一個新的state
let newState = {};
// 當咱們接收到一個action時,咱們沒法知道該交由哪一個reducer處理, 因此這裏咱們 須要遍歷全部reducer
for (let key in reducersObj){
newState[key] = reducersObj[key](state[key], action)
// 這樣一個reducer就成爲了store狀態樹中的子樹
// 好比頁面中有todo, counter兩個組件對應着兩個reducer, reducersObj = {todo, counter}
// store狀態樹大概長這樣: {todo: {list: [], counter: {number : 0}}
}
return newState;
}
}
最後將 combineReducer導出便可
combineReducer使用
通常來講,在一個app項目目錄中,咱們都會將reducer獨立出來,創建一個reducers文件夾,裏面就是各個app中所需的reducer, 而後這個文件夾裏還有一個index.js文件app
在這個index.js中咱們一般會先引入全部的reducer,而且引入combineReducer
函數
import counter from './counter';
...
import todo from './todo';
import { combineReducers } from "./../redux";
const rootReducer = combineReducers({
counter,
todo,
....
});
export default rootReducer;
在store.js文件中引入rootReducer
spa
import { createStore } from "redux";
import rootReducers from "./reducers/index";
export default const store = createStore(rootReducers);