# Store
上面章節中,我們學會了使用 [action](#) 來描述“發生了什么”,和使用 [reducers](#) 來根據 action 更新 state 的用法。
**Store** 就是把它們聯系到一起的對象。Store 有以下職責:
- 維持應用的 state;
- 提供 [`getState()`](#) 方法獲取 state;
- 提供 [`dispatch(action)`](#) 方法更新 state;
- 通過 [`subscribe(listener)`](#) 注冊監聽器。
再次強調一下 **Redux 應用只有一個單一的 store**。當需要拆分處理數據的邏輯時,使用 [reducer 組合](#) 而不是創建多個 store。
根據 reducer 創建 store 非常容易。例如,假如應用中只有一個 `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()`](#) 的第二個參數可以設置初始狀態。這對開發同構應用時非常有用,可以用于把服務器端生成的 state 轉變后在瀏覽器端傳給應用。
~~~
let store = createStore(todoApp, window.STATE_FROM_SERVER);
~~~
### 發起 Actions
創建好了 store 后,就可以驗證程序是否工作。雖然還沒有界面,我們已經可以測試更新邏輯了。
~~~
import { addTodo, completeTodo, setVisibilityFilter, VisibilityFilters } from './actions';
// 打印初始狀態
console.log(store.getState());
// 監聽 state 更新時,打印日志
let unsubscribe = store.subscribe(() =>
console.log(store.getState())
);
// 發起一系列 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));
// 停止監聽 state 更新
unsubscribe();
~~~
可以看到 store 里的 state 是如何變化的:

可以看到,在還沒有開發界面的時候,我們就可以定義程序的行為。而且這時候已經可以寫 reducer 和 action 創建函數的測試。不需要模擬任何東西,因為它們都是純函數。只需調用一下,對返回值做斷言,寫測試就是這么簡單。
### 源碼
#### `index.js`
~~~
import { combineReducers, createStore } from 'redux';
import * as reducers from './reducers';
let todoApp = combineReducers(reducers);
let store = createStore(todoApp);
~~~
### 下一步
在創建 todo 應用界面之前,我們先穿插學習一下[數據在 Redux 應用中如何流動的](#)。