# Redux 常見問題:創建 Store
## 目錄
- [可以創建多個 store 嗎,應該這么做嗎?能在組件中直接引用 store 并使用嗎?](#store-setup-multiple-stores)
- [在 store enhancer 中可以存在多個 middleware 鏈嗎? 在 middleware 方法中,next 和 dispatch 之間區別是什么?](#store-setup-middleware-chains)
- [怎樣只訂閱 state 的一部分變更?如何將分發的 action 作為訂閱的一部分?](#store-setup-subscriptions)
## 創建 Store
<a id="store-setup-multiple-stores"></a>
### 可以創建多個 store 嗎,應該這么做嗎?能在組件中直接引用 store 并使用嗎?
Flux 原始模型中一個應用有多個 “store”,每個都維護了不同維度的數據。這樣導致了類似于一個 store “等待” 另一 store 操作的問題。Redux 中將 reducer 分解成多個小而美的 reducer,進而切分數據域,避免了這種情況的發生。
正如上述問題所述,“可能” 在一個頁面中創建多個獨立的 Redux store,但是預設模式中只會有一個 store。僅維持單個 store 不僅可以使用 Redux DevTools,還能簡化數據的持久化及深加工、精簡訂閱的邏輯處理。
在 Redux 中使用多個 store 的理由可能包括:
- 對應用進行性能分析時,解決由于過于頻繁更新部分 state 引起的性能問題。
- 在更大的應用中 Redux 只是作為一個組件,這種情況下,你也許更傾向于為每個根組件創建單獨的 store。
然而,創建新的 store 不應成為你的第一反應,特別是當你從 Flux 背景遷移而來。首先嘗試組合 reducer,只有當它無法解決你的問題時才使用多個 store。
類似的,雖然你 _能_ 直接導入并獲取 store 實例,但這并非 Redux 的推薦方式。當你創建 store 實例并從組件導出,它將變成一個單例。這意味著將很難把 Redux 應用封裝成一個應用的子組件,除非這是必要的,或者為了實現服務端渲染需要為每一個請求創建單獨的 store 實例。
借助 [React Redux](https://github.com/rackt/react-redux),由 `connect()` 生成的包裝類實際上會檢索存在的 `props.store`,但還是推薦將根組件包裝在 `<Provider store={store}>` 中,這樣傳遞 store 的任務都交由 React Redux 處理。這種方式,我們不用考慮 store 模塊的導入、 Redux 應用的封裝,后期支持服務器渲染也將變得更為簡便。
#### 補充資料
**文檔**
- [API: Store](/docs/api/Store.md)
**討論**
- [#1346: Is it bad practice to just have a 'stores' directory?](https://github.com/reactjs/redux/issues/1436)
- [Stack Overflow: Redux multiple stores, why not?](http://stackoverflow.com/questions/33619775/redux-multiple-stores-why-not)
- [Stack Overflow: Accessing Redux state in an action creator](http://stackoverflow.com/questions/35667249/accessing-redux-state-in-an-action-creator)
- [Gist: Breaking out of Redux paradigm to isolate apps](https://gist.github.com/gaearon/eeee2f619620ab7b55673a4ee2bf8400)
<a id="store-setup-middleware-chains"></a>
### 在 store enhancer 中可以存在多個 middleware 鏈嗎? 在 middleware 方法中,`next` 和 `dispatch` 之間區別是什么?
Redux middleware 就像一個鏈表。每個 middleware 方法既能調用 `next(action)` 傳遞 action 到下一個 middleware,也可以調用 `dispatch(action)` 重新開始處理,或者什么都不做而僅僅終止 action 的處理進程。
創建 store 時, `applyMiddleware` 方法的入參定義了 middleware 鏈。定義多個鏈將無法正常執行,因為它們的 `dispatch` 引用顯然是不一樣的,而且不同的鏈也無法有效連接到一起。
#### 補充資料
**文檔**
- [Advanced: Middleware](/docs/advanced/Middleware.md)
- [API: applyMiddleware](/docs/api/applyMiddleware.md)
**討論**
- [#1051: Shortcomings of the current applyMiddleware and composing createStore](https://github.com/reactjs/redux/issues/1051)
- [Understanding Redux Middleware](https://medium.com/@meagle/understanding-87566abcfb7a)
- [Exploring Redux Middleware](http://blog.krawaller.se/posts/exploring-redux-middleware/)
<a id="store-setup-subscriptions"></a>
### 怎樣只訂閱 state 的一部分變更?如何將分發的 action 作為訂閱的一部分?
Redux 提供了獨立的 `store.subscribe` 方法用于通知監聽器 store 的變更信息。監聽器的回調方法并沒有把當前的 state 作為入參,它僅僅代表了 _有些數據_ 被更新。訂閱者的邏輯中調用 `getState()` 獲取當前的 state 值。
這個 API 是沒有依賴及副作用的底層接口,可以用于創建高階訂閱者邏輯。類似 React Redux 的 UI 綁定能為所有連接的組件都創建訂閱。也可以用于編寫智能的新舊 state 比對方法,從而在某些內容變化時執行額外的邏輯處理。示例 [redux-watch](https://github.com/jprichardson/redux-watch) 和 [redux-subscribe](https://github.com/ashaffer/redux-subscribe) 提供不同的方式用于指定訂閱及處理變更。
新的 state 沒有傳遞給監聽者,目的是簡化 store enhancer 的實現,比如 Redux DevTools。此外,訂閱者旨在響應 state 值本身,而非 action。當 action 很重要且需要特殊處理時,使用 middleware。
#### 補充資料
**文檔**
- [Basics: Store](/docs/basics/Store.md)
- [API: Store](/docs/api/Store.md)
**討論**
- [#303: subscribe API with state as an argument](https://github.com/reactjs/redux/issues/303)
- [#580: Is it possible to get action and state in store.subscribe?](https://github.com/reactjs/redux/issues/580)
- [#922: Proposal: add subscribe to middleware API](https://github.com/reactjs/redux/issues/922)
- [#1057: subscribe listener can get action param?](https://github.com/reactjs/redux/issues/1057)
- [#1300: Redux is great but major feature is missing](https://github.com/reactjs/redux/issues/1300)
**庫**
- [Redux Addons Catalog: Store Change Subscriptions](https://github.com/markerikson/redux-ecosystem-links/blob/master/store.md#store-change-subscriptions)
- 自述
- 介紹
- 動機
- 核心概念
- 三大原則
- 先前技術
- 學習資源
- 生態系統
- 示例
- 基礎
- 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
- 排錯