React高級篇(二)Redux工作流(react-redux)

《React高級篇(一)從Flux到Redux,react-redux》文章中貼過一張redux單向數(shù)據(jù)流的圖,但是,從action到reduer,其實還缺少了不少環(huán)節(jié)。

舉個例子,如果發(fā)起一個異步動作(比如網(wǎng)絡(luò)請求),該如何處理?redux單向數(shù)據(jù)流一定是同步的,碰上異步Action,必須將其轉(zhuǎn)為同步Action,才可以繼續(xù)走下去,否則事件會被丟失。

再比如,如果需要給每個Action都要打Log,那么,是否有個節(jié)點可以統(tǒng)一處理?

于是,store enhance(middleware是它的特殊實現(xiàn))出現(xiàn)了,Action到達reducer之前,會經(jīng)過一系列的enhancer處理看下圖:

redux flow.png

復習:Store的創(chuàng)建方式

createStore(reducer, [preloadedState], [enhancer])

第三個參數(shù)即是enhancer。

創(chuàng)建Store的enhancer

一個store對象中包含下列接口:

  • dispatch
  • subscribe
  • getState
  • replaceReducer

一般來說,自定義enhancer都是針對上述接口做能力增強,比如提供日志功能的logEnhancer,定義如下:

const logEnhancer = (createStore)  =>  (reducer,  preloadedState,  enhancer) =>  (
    const store= createStore(reducer,  preloadedState,  enhancer);
    const originalDispatch = store.dispatch;
    store.dispatch = (action) =>  {
        console.log('dispatch action:’,action);
        originalDispatch(action);
        return store;
};

增強器通常都使用這樣的模式,將store上某個函數(shù)的引用存下來,給這個函數(shù)一個新的實現(xiàn),但是在完成增強功能之后,還是要調(diào)用原有的函數(shù),保持原有的功能。

store enhancer和middleware的關(guān)系?

middleware本身就是一個store enhancer,它專門負責增強redux.dispatch()方法。middleware源碼示意如下:

export default function middleware(...middlewares) {
    return createStore => (...args) => 
        { // 省略 return { ...store, dispatch }
    }
}

注意:middleware應該置于enhancer隊列的最前排。

分發(fā)一個action時,middleware通過next(action)一層層處理和傳遞action到Redux原生的dispatch。
如果某個middleware使用store.dispatch(action))分發(fā)action,會跳出middleware管道,重新再來。如下圖:

redux.jpg
store.dispatch(action)的應用場景

action默認都是同步的。如果是一個異步Action(異步請求),那么需要一個專門處理異步請求的middleware,這是會用到store.dispatch()。這樣,異步工作流才可以被所有中間件處理,否則,它只能被當前位置之后的中間件處理。

常用的異步流中間件處理庫為redux-thunk。

const thunk = store =>next => action =>
    typeof action === 'function' ? action(store.dispatch, store.getState) : next(action)

異步Acton設(shè)計如下:發(fā)起異步請求,如果成功,彈出成功彈框,否則,彈出錯誤彈框。

const getThenShow = (dispatch, getState) =>{
    const url = 'http://xxx.json';

    fetch(url)
        .then(response=>{
            dispatch({
                type: 'SHOW_MESSAGE_SUCCESS',
                message: response.json
            })
        })
        .catch(error=>{
            dispatch({
                type: 'SHOW_MESSAGE_FAIL',
                message: 'error'
            })
        })
}

后記

講redux-thunk相關(guān)的文章非常多,不再累述。

參考文章:淺析Redux 的 store enhancer,書籍-《深入淺出react和redux》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容