# Store
在前面的章節中,我們學會了使用 [action](Actions.md) 來描述“發生了什么”,和使用 [reducers](Reducers.md) 來根據 action 更新 state 的用法。
**Store** 就是把它們聯系到一起的對象。Store 有以下職責:
- 維持應用的 state;
- 提供 [`getState()`](../api/Store.md#getState) 方法獲取 state;
- 提供 [`dispatch(action)`](../api/Store.md#dispatch) 方法更新 state;
- 通過 [`subscribe(listener)`](../api/Store.md#subscribe) 注冊監聽器;
- 通過 [`subscribe(listener)`](../api/Store.md#subscribe) 返回的函數注銷監聽器。
再次強調一下 **Redux 應用只有一個單一的 store**。當需要拆分數據處理邏輯時,你應該使用 [reducer 組合](Reducers.md#splitting-reducers) 而不是創建多個 store。
根據已有的 reducer 來創建 store 是非常容易的。在[前一個章節](Reducers.md)中,我們使用 [`combineReducers()`](../api/combineReducers.md) 將多個 reducer 合并成為一個。現在我們將其導入,并傳遞 [`createStore()`](../api/createStore.md)。
```js
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)
```
[`createStore()`](../api/createStore.md) 的第二個參數是可選的, 用于設置 state 初始狀態。這對開發同構應用時非常有用,服務器端 redux 應用的 state 結構可以與客戶端保持一致, 那么客戶端可以將從網絡接收到的服務端 state 直接用于本地數據初始化。
```js
let store = createStore(todoApp, window.STATE_FROM_SERVER)
```
## 發起 Actions
現在我們已經創建好了 store ,讓我們來驗證一下!雖然還沒有界面,我們已經可以測試數據處理邏輯了。
```js
import {
addTodo,
toggleTodo,
setVisibilityFilter,
VisibilityFilters
} from './actions'
// 打印初始狀態
console.log(store.getState())
// 每次 state 更新時,打印日志
// 注意 subscribe() 返回一個函數用來注銷監聽器
const 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(toggleTodo(0))
store.dispatch(toggleTodo(1))
store.dispatch(setVisibilityFilter(VisibilityFilters.SHOW_COMPLETED))
// 停止監聽 state 更新
unsubscribe()
```
可以看到 store 里的 state 是如何變化的:
<img src='http://i.imgur.com/zMMtoMz.png' width='70%'>
可以看到,在還沒有開發界面的時候,我們就可以定義程序的行為。而且這時候已經可以寫 reducer 和 action 創建函數的測試。不需要模擬任何東西,因為它們都是[純函數](../introduction/ThreePrinciples.md#使用純函數來執行修改)。只需調用一下,對返回值做斷言,寫測試就是這么簡單。
## 源碼
#### `index.js`
```js
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)
```
## 下一步
在創建 todo 應用界面之前,我們先穿插學習一下[數據在 Redux 應用中如何流動的](DataFlow.md)。
- 自述
- 介紹
- 動機
- 核心概念
- 三大原則
- 先前技術
- 學習資源
- 生態系統
- 示例
- 基礎
- Action
- Reducer
- Store
- 數據流
- 搭配 React
- 示例:Todo List
- 高級
- 異步 Action
- 異步數據流
- Middleware
- 搭配 React Router
- 示例:Reddit API
- 下一步
- 技巧
- 配置 Store
- 遷移到 Redux
- 使用對象展開運算符
- 減少樣板代碼
- 服務端渲染
- 編寫測試
- 計算衍生數據
- 實現撤銷重做
- 子應用隔離
- 組織 Reducer
- Reducer 基礎概念
- Reducer 基礎結構
- Reducer 邏輯拆分
- Reducer 重構示例
- combineReducers 用法
- combineReducers 進階
- State 范式化
- 管理范式化數據
- Reducer 邏輯復用
- 不可變更新模式
- 初始化 State
- 結合 Immutable.JS 使用 Redux
- 常見問題
- 綜合
- Reducer
- 組織 State
- 創建 Store
- Action
- 不可變數據
- 代碼結構
- 性能
- 設計哲學
- React Redux
- 其它
- 排錯
- 詞匯表
- API 文檔
- createStore
- Store
- combineReducers
- applyMiddleware
- bindActionCreators
- compose
- react-redux 文檔
- API
- 排錯