redux-thunk 是一个用于 Redux 的中间件(middleware)库,它可以让你在 Redux 中编写异步的 action creator。
在传统的 Redux 中,action creator 是一个简单的函数,用于创建一个 action 对象,并通过 dispatch 函数将该 action 对象发送给 Redux store。例如:
const fetchData = () => ({
type: 'FETCH_DATA',
});
然而,在实际开发中,有很多场景需要进行异步操作,例如发送网络请求获取数据。传统的 action creator 并不能直接处理异步操作,因为它只能返回一个简单的 action 对象。
这就是 redux-thunk 的作用。它允许你在 action creator 中返回一个函数而不是一个 action 对象。这个函数可以接收 dispatch 和 getState 作为参数,并可以在函数体内执行异步操作,最终再手动调用 dispatch 函数来发送真正的 action 对象。
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import rootReducer from './reducers';
// 应用 redux-thunk 中间件
const store = createStore(rootReducer, applyMiddleware(thunkMiddleware));
// 异步 action creator
const fetchData = () => {
return (dispatch, getState) => {
// 可以在这里执行异步操作,例如发送网络请求获取数据
dispatch({ type: 'FETCH_DATA_REQUEST' });
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
})
.catch(error => {
dispatch({ type: 'FETCH_DATA_FAILURE', payload: error.message });
});
};
};
// 调用异步 action creator
store.dispatch(fetchData());
在上面的示例中,我们通过 applyMiddleware 将 redux-thunk 中间件应用到 Redux store 中。然后,我们定义了一个异步 action creator fetchData,它返回一个函数而不是一个 action 对象。在函数体内,我们可以执行异步操作,并根据操作的结果手动调用 dispatch 函数来发送不同的 action 对象,从而实现了异步操作的处理。
总结一下,redux-thunk 允许我们在 Redux 中编写异步操作,使得 action creator 可以返回一个函数,从而处理复杂的异步场景。
源码
function createThunkMiddleware<
State = any,
BasicAction extends Action = AnyAction,
ExtraThunkArg = undefined
>(extraArgument?: ExtraThunkArg) {
// Standard Redux middleware definition pattern:
// See: https://redux.js.org/tutorials/fundamentals/part-4-store#writing-custom-middleware
const middleware: ThunkMiddleware<State, BasicAction, ExtraThunkArg> =
({ dispatch, getState }) =>
next =>
action => {
// The thunk middleware looks for any functions that were passed to `store.dispatch`.
// If this "action" is really a function, call it and return the result.
if (typeof action === 'function') {
// Inject the store's `dispatch` and `getState` methods, as well as any "extra arg"
return action(dispatch, getState, extraArgument)
}
// Otherwise, pass the action down the middleware chain as usual
return next(action)
}
return middleware
}
export const thunk = createThunkMiddleware()
关键代码
if (typeof action === 'function') {
// Inject the store's `dispatch` and `getState` methods, as well as any "extra arg"
return action(dispatch, getState, extraArgument)
}
在这段代码中,action(dispatch, getState, extraArgument) 是一个处理异步 action 的关键步骤。这里 action 是通过 store.dispatch 派发的 action,如果它是一个函数(也就是一个 thunk action),那么中间件会将其执行,并且将 dispatch 和 getState 以及可能的额外参数 extraArgument 传递给这个函数。
在这段代码中,action(dispatch, getState, extraArgument) 是一个处理异步 action 的关键步骤。这里 action 是通过 store.dispatch 派发的 action,如果它是一个函数(也就是一个 thunk action),那么中间件会将其执行,并且将 dispatch 和 getState 以及可能的额外参数 extraArgument 传递给这个函数。
具体地说:
dispatch是 Redux store 的dispatch方法,它用于派发 action。getState是 Redux store 的getState方法,它用于获取当前的 state。extraArgument是可选的额外参数,可以在创建thunkMiddleware时传入,用于在 thunk action 中传递一些额外的数据。
当中间件检测到 action 是一个函数(thunk action)时,它会调用这个函数,并将上述参数传递给它。通常情况下,这个函数会包含异步的逻辑,例如异步请求数据或者进行一些延时操作。在函数执行完成后,它可能会返回一个对象(普通 action)或者什么都不返回(异步 action)。如果返回一个对象,这个对象会被传递给下一个中间件或者最终的 reducer 处理;如果没有返回任何内容,那么中间件链将会终止,不再向下传递这个 action,也就是说异步操作完成后不会再有其他 action 发生。