combineReducers(reducers)
隨著應(yīng)用變得復(fù)雜,需要對(duì) reducer 函數(shù) 進(jìn)行拆分,拆分后的每一塊獨(dú)立負(fù)責(zé)管理 state 的一部分。
combineReducers
輔助函數(shù)的作用是,把一個(gè)由多個(gè)不同 reducer 函數(shù)作為 value 的 object,合并成一個(gè)最終的 reducer 函數(shù),然后就可以對(duì)這個(gè) reducer 調(diào)用 createStore
。
合并后的 reducer 可以調(diào)用各個(gè)子 reducer,并把它們的結(jié)果合并成一個(gè) state 對(duì)象。state 對(duì)象的結(jié)構(gòu)由傳入的多個(gè) reducer 的 key 決定。
Flux 用戶使用須知
本函數(shù)可以幫助你組織多個(gè) reducer,使它們分別管理自身相關(guān)聯(lián)的 state。類(lèi)似于 Flux 中的多個(gè) store 分別管理不同的 state。在 Redux 中,只有一個(gè) store,但是
combineReducers
讓你擁有多個(gè) reducer,同時(shí)保持各自負(fù)責(zé)邏輯塊的獨(dú)立性。
reducers
(Object): 一個(gè)對(duì)象,它的值(value) 對(duì)應(yīng)不同的 reducer 函數(shù),這些 reducer 函數(shù)后面會(huì)被合并成一個(gè)。下面會(huì)介紹傳入 reducer 函數(shù)需要滿足的規(guī)則。之前的文檔曾建議使用 ES6 的
import * as reducers
語(yǔ)法來(lái)獲得 reducer 對(duì)象。這一點(diǎn)造成了很多疑問(wèn),因此現(xiàn)在建議在reducers/index.js
里使用combineReducers()
來(lái)對(duì)外輸出一個(gè) reducer。下面有示例說(shuō)明。
(Function): 一個(gè)調(diào)用 reducers
對(duì)象里所有 reducer 的 reducer,并且構(gòu)造一個(gè)與 reducers
對(duì)象結(jié)構(gòu)相同的 state 對(duì)象。
本函數(shù)設(shè)計(jì)的時(shí)候有點(diǎn)偏主觀,就是為了避免新手犯一些常見(jiàn)錯(cuò)誤。也因些我們故意設(shè)定一些規(guī)則,但如果你自己手動(dòng)編寫(xiě)根 redcuer 時(shí)并不需要遵守這些規(guī)則。
每個(gè)傳入 combineReducers
的 reducer 都需滿足以下規(guī)則:
所有未匹配到的 action,必須把它接收到的第一個(gè)參數(shù)也就是那個(gè) state
原封不動(dòng)返回。
永遠(yuǎn)不能返回 undefined
。當(dāng)過(guò)早 return
時(shí)非常容易犯這個(gè)錯(cuò)誤,為了避免錯(cuò)誤擴(kuò)散,遇到這種情況時(shí) combineReducers
會(huì)拋異常。
如果傳入的 state
就是 undefined
,一定要返回對(duì)應(yīng) reducer 的初始 state。根據(jù)上一條規(guī)則,初始 state 禁止使用 undefined
。使用 ES6 的默認(rèn)參數(shù)值語(yǔ)法來(lái)設(shè)置初始 state 很容易,但你也可以手動(dòng)檢查第一個(gè)參數(shù)是否為 undefined
。
雖然 combineReducers
自動(dòng)幫你檢查 reducer 是否符合以上規(guī)則,但你也應(yīng)該牢記,并盡量遵守。
reducers/todos.js
export default function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([action.text]);
default:
return state;
}
}
reducers/counter.js
export default function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
reducers/index.js
import { combineReducers } from 'redux';
import todos from './todos';
import counter from './counter';
export default combineReducers({
todos,
counter
});
App.js
import { createStore } from 'redux';
import reducer from './reducers/index';
let store = createStore(reducer);
console.log(store.getState());
// {
// counter: 0,
// todos: []
// }
store.dispatch({
type: 'ADD_TODO',
text: 'Use Redux'
});
console.log(store.getState());
// {
// counter: 0,
// todos: ['Use Redux']
// }
本方法只是起輔助作用!你可以自行實(shí)現(xiàn)不同功能的 combineReducers
,甚至像實(shí)現(xiàn)其它函數(shù)一樣,明確地寫(xiě)一個(gè)根 reducer 函數(shù),用它把子 reducer 手動(dòng)組裝成 state 對(duì)象。
在 reducer 層級(jí)的任何一級(jí)都可以調(diào)用 combineReducers
。并不是一定要在最外層。實(shí)際上,你可以把一些復(fù)雜的子 reducer 拆分成單獨(dú)的孫子級(jí) reducer,甚至更多層。
更多建議: