iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 21
1
Modern Web

寫React的那些事系列 第 21

React Day21 - Redux Store

Store


Redux中只會有一個store,還記得前面幾天我們說的 「Single source of truth」 嗎?Store就是每個state組成的state tree,用來管理專案中所有的state,上一篇我們用combineReducers()把reducers組合在一起,包成一個大~reducer,再來我們要用createStore()來產生完整的store。

一般來說,如果我們只有一個reducer,我們可以透過createStore()來產生對應的一個state:

import { createStore } from 'redux';
import todo from './reducers/todo';

// store會是 { todo: [] }
let store = createStore(todo);

當我們透過前一天說的combineReducers()組合多個reducer,就會是這樣指定給store:

import { createStore } from 'redux';
import todoApp from './reducers';

// store會是 { todo: [], filter: 'SHOW_ALL' }
let store = createStore(todoApp);

當store被建立的時候,Redux會先dispatch一個action,這會讓reducer先把預設的state設定到store中,所以當我們在寫reducer funtion的時候,記得要帶入預設值,否則該state一開始會是undefined。

Store儲存了一個state tree,但它不只是這樣,它還提供了一些方法可以使用:

  • getState()
  • dispatch(action)
  • subscribe(listener)
  • replaceReducer(nextReducer)

以下先介紹一下這些方法。

getState()


它會傳回當下store儲存的state tree object,有時候在產生action時,會需要依據其他state來處理,這時候就可以用getState()來取得目前的state。例如要取得todo目前的值,可以呼叫getState().todo

dispatch(action)


透過dispatch發送一個action,這是Redux中唯一改變state的方式。

subscribe(listener)


設定一個listener事件,state一旦發生變化,就會呼叫這個listener,在listener裡面可以用store.getState()來取得當前的state tree。 (不過,一般來說很少會用到這個方法,可以先參考看看就好。)

replaceReducer(nextReducer)


替換產生store的reducer,這是在已經建立store之後,如果要把原本的某個state對應到不同的reducer function。 (通常也是很少會用到,所以這邊列出來參考即可。)

觀察變化


有了這些store的概念後,我們在原本的todos範例中,加上createStore(todoApp)產生store,再使用剛剛提到的兩個store方法,就可以從log看到actions、reducers與store之間的變化囉!

  • 先用createStore(rootReducer)建立store。
  • 再用store.getState()看看目前的state tree,filter為SHOW_ALL,todos初始值為空陣列,跟我們在reducer function預設的一樣。
  • 建立store.subscribe,每當state發生變化,再印出state tree目前狀態。
  • store.dispatch(action),這邊新增task進去。
  • 可以從log上看到,兩個state tree不一樣的地方,todos陣列多一個我們剛剛新增的Test。

完整index.js程式碼:

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';

import * as todoActions from './actions/todos';
import todoApp from './reducers';
import App from './app';

// 建立store
let store = createStore(todoApp);
// 初始store值
console.log(store.getState());

// 透過store.subscribe,偵聽store變化記錄log
let listener = store.subscribe(() =>
  console.log(store.getState())
);
// 使用store.dispatch,發送action
store.dispatch(todoActions.addTask('Test'));

ReactDOM.render(
  <App />,
  document.getElementById('main')
);

可以參考這張圖,觀察log情形:
http://ithelp.ithome.com.tw/upload/images/20161221/20078318IZUsSlsCvv.png

目前我們還沒有把Redux跟React做結合,但Redux的精神已經實作完成!下一階段就會說明把Redux和React結合的方式囉!今天的檔案已經放在Git上,可以執行 npm run dev 看到log的結果喔!(如果沒有的話,請再次執行npm install看看,因為這次有加上redux的package喔!)


上一篇
React Day20 - Redux Reducer
下一篇
React Day22 - 串接React和Redux
系列文
寫React的那些事31

尚未有邦友留言

立即登入留言