Store 就是用來維持應(yīng)用所有的 state 樹 的一個對象。
改變 store 內(nèi) state 的惟一途徑是對它 dispatch 一個 action。
Store 不是類。它只是有幾個方法的對象。
要創(chuàng)建它,只需要把根部的 reducing 函數(shù) 傳遞給 createStore
。
Flux 用戶使用注意
如果你以前使用 Flux,那么你只需要注意一個重要的區(qū)別。Redux 沒有 Dispatcher 且不支持多個 store。相反,只有一個單一的 store 和一個根級的 reduce 函數(shù)(reducer)。隨著應(yīng)用不斷變大,你應(yīng)該把根級的 reducer 拆成多個小的 reducers,分別獨(dú)立地操作 state 樹的不同部分,而不是添加新的 stores。這就像一個 React 應(yīng)用只有一個根級的組件,這個根組件又由很多小組件構(gòu)成。
getState()
返回應(yīng)用當(dāng)前的 state 樹。
它與 store 的最后一個 reducer 返回值相同。
(any): 應(yīng)用當(dāng)前的 state 樹。
dispatch(action)
分發(fā) action。這是觸發(fā) state 變化的惟一途徑。
會使用當(dāng)前 getState()
的結(jié)果和傳入的 action
以同步方式的調(diào)用 store 的 reduce 函數(shù)。返回值會被作為下一個 state。從現(xiàn)在開始,這就成為了 getState()
的返回值,同時變化監(jiān)聽器(change listener)會被觸發(fā)。
Flux 用戶使用注意
當(dāng)你在 reducer 內(nèi)部調(diào)用
dispatch
時,將會拋出錯誤提示“Reducers may not dispatch actions.(Reducer 內(nèi)不能 dispatch action)”。這就相當(dāng)于 Flux 里的 “Cannot dispatch in a middle of dispatch(dispatch 過程中不能再 dispatch)”,但并不會引起對應(yīng)的錯誤。在 Flux 里,當(dāng) Store 處理 action 和觸發(fā) update 事件時,dispatch 是禁止的。這個限制并不好,因?yàn)樗拗屏瞬荒茉谏芷诨卣{(diào)里 dispatch action,還有其它一些本來很正常的地方。在 Redux 里,只會在根 reducer 返回新 state 結(jié)束后再會調(diào)用事件監(jiān)聽器,因此,你可以在事件監(jiān)聽器里再做 dispatch。惟一使你不能在 reducer 中途 dispatch 的原因是要確保 reducer 沒有副作用。如果 action 處理會產(chǎn)生副作用,正確的做法是使用異步 action 創(chuàng)建函數(shù)。
action
(Object?): 描述應(yīng)用變化的普通對象。Action 是把數(shù)據(jù)傳入 store 的惟一途徑,所以任何數(shù)據(jù),無論來自 UI 事件,網(wǎng)絡(luò)回調(diào)或者是其它資源如 WebSockets,最終都應(yīng)該以 action 的形式被 dispatch。按照約定,action 具有 type
字段來表示它的類型。type 也可被定義為常量或者是從其它模塊引入。最好使用字符串,而不是 Symbols 作為 action,因?yàn)樽址强梢员恍蛄谢?。除?type
字段外,action 對象的結(jié)構(gòu)完全取決于你。參照 Flux 標(biāo)準(zhǔn) Action 獲取如何組織 action 的建議。(Object?): 要 dispatch 的 action。
? 使用 createStore
創(chuàng)建的 “純正” store 只支持普通對象類型的 action,而且會立即傳到 reducer 來執(zhí)行。
但是,如果你用 applyMiddleware
來套住 createStore
時,middleware 可以修改 action 的執(zhí)行,并支持執(zhí)行 dispatch intent(意圖)。Intent 一般是異步操作如 Promise、Observable 或者 Thunk。
Middleware 是由社區(qū)創(chuàng)建,并不會同 Redux 一起發(fā)行。你需要手動安裝 redux-thunk 或者 redux-promise 庫。你也可以創(chuàng)建自己的 middleware。
想學(xué)習(xí)如何描述異步 API 調(diào)用?看一下 action 創(chuàng)建函數(shù)里當(dāng)前的 state,執(zhí)行一個有副作用的操作,或者以鏈?zhǔn)讲僮鲌?zhí)行它們,參照 applyMiddleware
中的示例。
import { createStore } from 'redux';
let store = createStore(todos, ['Use Redux']);
function addTodo(text) {
return {
type: 'ADD_TODO',
text
};
}
store.dispatch(addTodo('Read the docs'));
store.dispatch(addTodo('Read about the middleware'));
subscribe(listener)
添加一個變化監(jiān)聽器。每當(dāng) dispatch action 的時候就會執(zhí)行,state 樹中的一部分可能已經(jīng)變化。你可以在回調(diào)函數(shù)里調(diào)用 getState()
來拿到當(dāng)前 state。
這是一個底層 API。多數(shù)情況下,你不會直接使用它,會使用一些 React(或其它庫)的綁定。如果你想讓回調(diào)函數(shù)執(zhí)行的時候使用當(dāng)前的 state,你可以 把 store 轉(zhuǎn)換成一個 Observable 或者寫一個定制的 observeStore
工具。
如果需要解綁這個變化監(jiān)聽器,執(zhí)行 subscribe
返回的函數(shù)即可。
listener
(Function): 每當(dāng) dispatch action 的時候都會執(zhí)行的回調(diào)。state 樹中的一部分可能已經(jīng)變化。你可以在回調(diào)函數(shù)里調(diào)用 getState()
來拿到當(dāng)前 state。store 的 reducer 應(yīng)該是純函數(shù),因此你可能需要對 state 樹中的引用做深度比較來確定它的值是否有變化。(Function): 一個可以解綁變化監(jiān)聽器的函數(shù)。
function select(state) {
return state.some.deep.property;
}
let currentValue;
function handleChange() {
let previousValue = currentValue;
currentValue = select(store.getState());
if (previousValue !== currentValue) {
console.log('Some deep nested property changed from', previousValue, 'to', currentValue);
}
}
let unsubscribe = store.subscribe(handleChange);
handleChange();
replaceReducer(nextReducer)
替換 store 當(dāng)前用來計算 state 的 reducer。
這是一個高級 API。只有在你需要實(shí)現(xiàn)代碼分隔,而且需要立即加載一些 reducer 的時候才可能會用到它。在實(shí)現(xiàn) Redux 熱加載機(jī)制的時候也可能會用到。
reducer
(Function) store 會使用的下一個 reducer。
更多建議: