参考 : 理解redux-thunk
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是作为redux的 middleware 存在的,用法和普通 middleware 的用法是一样的,注册 middleware 的代码如下:
import thunk from 'redux-thunk'
const store = createStore(reducer, applyMiddleware(thunk))
注册后可以这样使用:
// 用于发起登录请求,并处理请求结果
// 接受参数用户名,并返回一个函数(参数为dispatch)
const login = (userName) => (dispatch) => {
dispatch({ type: 'loginStart' })
request.post('/api/login', { data: userName }, () => {
dispatch({ type: 'loginSuccess', payload: userName })
})
}
store.dispatch(login('Lucy'))
PS : login本身是一个嵌套函数, 返回值是一个函数, 所以 login('Lucy') 返回的就是一个函数, 所以这里就是dispatch(function)
可以看到,redux-thunk主要的功能就是可以让我们dispatch一个函数,而不只是普通的 Object。后面我们会看到,这一点改变可以给我们巨大的灵活性。
了解了如何使用,接下来我们看一下它的实现原理。
起源
redux-thunk的代码和原理非常简单,但我觉得难的部分是为什么需要这样一个库。关于redux-thunk的起源可以看一下 Redux 001 号的 issue: How to dispatch many actions in one action creator[1]
大概意思就是问如何一次性发起多个 action,然后作者回答我可以让 actionCreator 返回一个函数。然后相关的 PR 如下: fix issue 001[2]
为什么需要?
现在我们理解了redux-thunk可以让我们 dispatch 一个 function,但是这有什么用呢?其实我觉得这是一项基础设施,虽然功能简单,但可扩展性极其强大。
比如很多时候我们需要在一个函数中写多次 dispatch。这也是上面 issue 中提到的问题。比如上面我们示例代码中,我们定义了 login 函数做 API 请求,在请求发出前我们可能需要展示一个全局的 loading bar,在请求结束后我们又需要将请求结果存储到 redux store 中。这都需要用到 redux 的 dispatch。
当然在一个函数中写多个 dispatch 只是我们可以做的事情之一,既然它是一个 function,而且并不要求像 reducer 一样是 pure function,那么我们可以在其中做任意的事情,也就是有副作用(side effect)的事情。
简单粗暴的总结
1 .如果我们的需求中, 想要在一个函数中做多次dispatch, 并且相互有关联, 如嵌套函数的方式, 那就可以使用thunk解决这个需求.
- 普通的redux中,
dispatch(object)
, thunk中dispatch(function)
实例
注册
import { createStore, applyMiddleware } from 'redux';
import thunks from 'redux-thunk';
import getReducers from '../Reducers';
export default function getStore() {
return createStore(
getReducers(),
applyMiddleware(thunks, logger)
);
}
创建函数
/**
* 检查手机网络
*/
export const checkNetwork = () => {
return async (dispatch) => {
// 获取网络状态
const netConnectStatus = await NetworkUtils.checkNetworkConnected();
if (!netConnectStatus) {
dispatch({
type: UPDATE_NETWORK_ERROR_DIALOG,
showNetworkErrorDialog: true
});
}
};
};
(某个Page初始化)调用时机
componentDidMount() {
this.props.dispatch(checkNetwork());
}
总结
简单粗暴理解为:
ReactNative Redux flow是同步数据处理
redux-thunk是异步数据处理, 也就是异步处理+Redux
3.这样做的好处就是把所有的业务逻辑封装在action里面.. 某一个页面的page在componentDidMount只需要调一个方法就可以了. 代码管理起来就简洁很多了