上面章節(jié)中,我們學(xué)會了使用 action 來描述“發(fā)生了什么”,和使用 reducers 來根據(jù) action 更新 state 的用法。
Store 就是把它們聯(lián)系到一起的對象。Store 有以下職責(zé):
getState()
方法獲取 state;dispatch(action)
方法更新 state;subscribe(listener)
注冊監(jiān)聽器。再次強調(diào)一下 Redux 應(yīng)用只有一個單一的 store。當(dāng)需要拆分處理數(shù)據(jù)的邏輯時,使用 reducer 組合 而不是創(chuàng)建多個 store。
根據(jù) reducer 創(chuàng)建 store 非常容易。例如,假如應(yīng)用中只有一個 todoApp
的 reducer,可以這樣寫:
import { createStore } from 'redux';
import todoApp from './reducers';
let store = createStore(todoApp);
為了提高可維護性,拆分成多個 reducer,這時需要使用 combineReducers()
來把它們組合起來。
import { combineReducers, createStore } from 'redux';
import * as reducers from './reducers';
let todoApp = combineReducers(reducers);
let store = createStore(todoApp);
createStore()
的第二個參數(shù)可以設(shè)置初始狀態(tài)。這對開發(fā)同構(gòu)應(yīng)用時非常有用,可以用于把服務(wù)器端生成的 state 轉(zhuǎn)變后在瀏覽器端傳給應(yīng)用。
let store = createStore(todoApp, window.STATE_FROM_SERVER);
創(chuàng)建好了 store 后,就可以驗證程序是否工作。雖然還沒有界面,我們已經(jīng)可以測試更新邏輯了。
import { addTodo, completeTodo, setVisibilityFilter, VisibilityFilters } from './actions';
// 打印初始狀態(tài)
console.log(store.getState());
// 監(jiān)聽 state 更新時,打印日志
let unsubscribe = store.subscribe(() =>
console.log(store.getState())
);
// 發(fā)起一系列 action
store.dispatch(addTodo('Learn about actions'));
store.dispatch(addTodo('Learn about reducers'));
store.dispatch(addTodo('Learn about store'));
store.dispatch(completeTodo(0));
store.dispatch(completeTodo(1));
store.dispatch(setVisibilityFilter(VisibilityFilters.SHOW_COMPLETED));
// 停止監(jiān)聽 state 更新
unsubscribe();
可以看到 store 里的 state 是如何變化的:
可以看到,在還沒有開發(fā)界面的時候,我們就可以定義程序的行為。而且這時候已經(jīng)可以寫 reducer 和 action 創(chuàng)建函數(shù)的測試。不需要模擬任何東西,因為它們都是純函數(shù)。只需調(diào)用一下,對返回值做斷言,寫測試就是這么簡單。
index.js
import { combineReducers, createStore } from 'redux';
import * as reducers from './reducers';
let todoApp = combineReducers(reducers);
let store = createStore(todoApp);
在創(chuàng)建 todo 應(yīng)用界面之前,我們先穿插學(xué)習(xí)一下數(shù)據(jù)在 Redux 應(yīng)用中如何流動的。
更多建議: