React+Redux之redux-thunk作用

redux-thunk 是一个比较流行的 redux 异步 action 中间件。redux-thunk 帮助你统一了异步和同步 action 的调用方式,把异步过程放在 action 级别解决,对 component 没有影响。下面通过例子一步步来看看。

异步方法的调用

store.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
  store.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)

这是一个简单的例子,他做事情很简单,5s 后关闭提醒。

在一个被 redux connect 过的 component 中,是如下这个样子:

this.props.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
  this.props.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)

本质上两者没有区别,只是被 connect 过的 component 中的 ****this.props**** 有了 ****dispatch**** 属性。

redux-thunk源码

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }
    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

redux-thunk的源码非常简洁,出去空格一共只有11行,这11行中如果不算上},则只有8行。最后三行模块的导出方法很好理解,

// thunk.withExtraArgument的结果如下
function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }
    return next(action);
  };
}

thunk.withExtraArgument允许给返回的函数传入额外的参数,它比较难理解的部分和thunk一样,如下:

({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }
    return next(action);
  }

上述代码使用函数参数的解构加上连用三个箭头函数,显得非常简洁,单同时也带来了理解的困难(这也是箭头函数的缺点之一)。把上述代码在babel REPL中转译为ES5语法后,我们看到以下结果:

"use strict";

function createThunkMiddleware(extraArgument) {
  return function (_ref) {
    var dispatch = _ref.dispatch,
        getState = _ref.getState;
    return function (next) {
      return function (action) {
        if (typeof action === "function") {
          return action(dispatch, getState, extraArgument);
        }
        return next();
      };
    };
  };
}

这下,代码一下子我们能看懂了,不过稍等这里的dispatch,getStatenext还有action又是什么?

我们先看看,在reudx中我们如何使用中间件:

let store = createStore(
    reducer,
    applyMiddleware(thunk)
);

看来,要解开dispatch,getState,next,action从哪里来,我们还需要再看看applyMiddleware的源码,如下:

export default function applyMiddleware(...middlewares) {
  return (createStore) => (...args) => {
    const store = createStore(...args)
    let dispatch = store.dispatch
    let chain = []

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

可以看出其中middleware执行时传入的参数对象middlewareAPI中确实包含getStatedispatch两项,next则来自dispatch = compose(...chain)(store.dispatch)这一句中的store.dispatch,而actiondispatch某个action时传入。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容