做了一些關於redux 內部如何運作的research,有任何疑間請不吝分享討論。
碰過flux的人對於這張圖應該是看到不要再看 且讓我們以這張圖為出發點,假裝我們自已是使用者,使用者看到的是網頁,所以請你由React View出發 View --> ActionCreators --> Dispatcher --> Store --> (Render View) | | | | <------------------------------------------------------------------------------------------------
實際上在redux的圖應該是這樣(參考圖)
View --> ActionCreator --> Store(middleware,reducer,state)Loop --> View(Provider,connect) | | | | <------------------------------------------------------------------------------------------------
為什麼呢?這就要從 createStore這個method看起了 https://github.com/rackt/redux/blob/master/src/createStore.js input 是 reducer和 initialState 兩個參數 output 是 dispatch,subscribe,getState,replaceReducer組成的物件。
replaceReducer:做的行為就是一個一個把reducer設定為初始化狀態。 getState:取得當下的state subscribe: 一個listener,當action被執行的時候發生,通常會有一個callback來執行getState方法。 dispatch: 提供dispatch(action)去觸發每一個動作。
於是你至少知道一件事,store本身就包含了reducer(其實是combineReducer),和initialState。 另一件事,store自已就可以控制要經過哪個reducer來得到state。
而redux middleware作用的方式其實是經過這樣的包裝(此處只留下必要的code)
import { createStore,combineReducers, applyMiddleware,compose } from 'redux';
import thunk from 'redux-thunk';
import * as reducers from '../reducers';
import promiseMiddleware from 'redux-promise-middleware';
const createStoreWithMiddleware = compose(
applyMiddleware(thunk,promiseMiddleware())
)(createStore);
const rootReducer = combineReducers(reducers);
export default function configureStore(initialState) {
const store = createStoreWithMiddleware(rootReducer, initialState);
return store;
}
createStoreWithMiddleware把createStore整個包裝了起來, 於是middleware就可以在store中自由的穿插, 要寫log有redux-logger, 要寫fetch有redux-promise-middleware, 想要寫一個action來觸發其他的action就可以用redux-thunk.
這樣我們就可以依照我們的需求來控制動作(action)和狀態(state)之間的關係啦。
小結
由前面的流程做為出發點 View --> ActionCreator --> Store(middleware,reducer,state)Loop --> View(Provider,connect) | | | | <------------------------------------------------------------------------------------------------
store實際上有一層層的包裝 這其實是functional language的概念 給定沒有副作用的function(reducer)和一個定值(state),每次出來的結果都會相同。
然而實際redux應用在專案開發上有另外做處理來簡化你的開發流程。 除了前面講到的createStore之外
其一是combineReducer,不但合併你的每一個reducer,而且合併它產出的state. 其二是bindActionCreator,透過和store.dispatch綁定後
let bindActionCreator => (actionCreator, dispatch) {
return (...args) => dispatch(actionCreator(...args));
}
我們就可以把actionCreator轉化成實際可以用的action了。
挺好,几张图就可以理解原理,加精