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

2021-01-14 15:10:08 浏览数 (1)

在《React高级篇(一)从Flux到Redux,react-redux》文章中贴过一张redux单向数据流的图,但是,从action到reduer,其实还缺少了不少环节。

举个例子,如果发起一个异步动作(比如网络请求),该如何处理?redux单向数据流一定是同步的,碰上异步Action,必须将其转为同步Action,才可以继续走下去,否则事件会被丢失。

再比如,如果需要给每个Action都要打Log,那么,是否有个节点可以统一处理?

于是,store enhance(middleware是它的特殊实现)出现了,Action到达reducer之前,会经过一系列的enhancer处理看下图:

redux flow.png

复习:Store的创建方式

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

第三个参数即是enhancer

创建Store的enhancer

一个store对象中包含下列接口:

  • dispatch
  • subscribe
  • getState
  • replaceReducer

一般来说,自定义enhancer都是针对上述接口做能力增强,比如提供日志功能的logEnhancer,定义如下:

代码语言:javascript复制
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上某个函数的引用存下来,给这个函数一个新的实现,但是在完成增强功能之后,还是要调用原有的函数,保持原有的功能。

store enhancer和middleware的关系?

middleware本身就是一个store enhancer,它专门负责增强redux.dispatch()方法。middleware源码示意如下:

代码语言:javascript复制
export default function middleware(...middlewares) {
    return createStore => (...args) => 
        { // 省略 return { ...store, dispatch }
    }
}

注意:middleware应该置于enhancer队列的最前排。

分发一个action时,middleware通过next(action)一层层处理和传递action到Redux原生的dispatch。

如果某个middleware使用store.dispatch(action))分发action,会跳出middleware管道,重新再来。如下图:

redux.jpg

store.dispatch(action)的应用场景

action默认都是同步的。如果是一个异步Action(异步请求),那么需要一个专门处理异步请求的middleware,这是会用到store.dispatch()。这样,异步工作流才可以被所有中间件处理,否则,它只能被当前位置之后的中间件处理。

常用的异步流中间件处理库为redux-thunk。

代码语言:javascript复制
const thunk = store =>next => action =>
    typeof action === 'function' ? action(store.dispatch, store.getState) : next(action)

异步Acton设计如下:发起异步请求,如果成功,弹出成功弹框,否则,弹出错误弹框。

代码语言:javascript复制
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相关的文章非常多,不再累述。

参考文章:浅析Redux 的 store enhancer,书籍-《深入浅出react和redux》

0 人点赞