为什么在 react 中调用的 action 函数被包裹在 dispatch 中?
Why are action function called wrapped inside dispatch in react?
我刚刚在网上浏览了一些 react-redux 代码,基本上我遇到了下面的一组代码,它基本上是一个充满 ACTIONS
的 js 文件,只是为了提供一些 redux 组合的上下文此处使用 redux-thunk:
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
await dispatch(getConfig());
await dispatch(getGenres());
dispatch({ type: TYPES.REMOVE_LOADING });
};
// Action Creator to get the config object from the API
export const getConfig = () => async dispatch => {
const res = await tmdbAPI.get('/configuration');
dispatch({
type: TYPES.GET_CONFIG,
payload: res.data,
});
};
我有点困惑为什么 getConfig
函数被包裹在 dispatch
中?
Redux thunk 只是可以执行副作用的 redux 操作。所以
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
await dispatch(getConfig());
await dispatch(getGenres());
dispatch({ type: TYPES.REMOVE_LOADING });
};
只是一个异步初始化函数,调用时以同步方式执行步骤。
关键是 thunk 可以分派其他 thunks/actions/etc 所以 init thunk 只是分派本身是异步的 getConfig()
操作,所以 init 函数的下一步直到配置 API 调用完成(可能是因为其他一些代码依赖于它)
如果你不想,请不要包装
像这样
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
dispatch(await getConfig());
dispatch({ type: TYPES.REMOVE_LOADING });
};
//this is not using redux-thunk
// Action Creator to get the config object from the API
export const getConfig = async () => {
const res = await tmdbAPI.get('/configuration');
return {
type: TYPES.GET_CONFIG,
payload: res.data,
};
};
重要
但是有很多原因为什么要用 dispatch 包装动作。
举一个例子。
当你想一步一步获取多个数据时
export const getData = () => async dispatch => {
dispatch({
type: DATA_LOADING_START
});
try {
const res = await tmdbAPI.get('/url1');
dispatch({
type: DATA1_LOADED,
payload: res.data,
});
const res = await tmdbAPI.get('/url2');
dispatch({
type: DATA2_LOADED,
payload: res.data,
});
} catch (err) {
// handle error
}
dispatch({
type: DATA_LOADING_END
});
};
//this is using redux-thunk
@AlexanderSolonik
问题: 为什么要通过调度包装动作?
因为dispatch()
将动作结果发送给reducer。
我刚刚在网上浏览了一些 react-redux 代码,基本上我遇到了下面的一组代码,它基本上是一个充满 ACTIONS
的 js 文件,只是为了提供一些 redux 组合的上下文此处使用 redux-thunk:
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
await dispatch(getConfig());
await dispatch(getGenres());
dispatch({ type: TYPES.REMOVE_LOADING });
};
// Action Creator to get the config object from the API
export const getConfig = () => async dispatch => {
const res = await tmdbAPI.get('/configuration');
dispatch({
type: TYPES.GET_CONFIG,
payload: res.data,
});
};
我有点困惑为什么 getConfig
函数被包裹在 dispatch
中?
Redux thunk 只是可以执行副作用的 redux 操作。所以
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
await dispatch(getConfig());
await dispatch(getGenres());
dispatch({ type: TYPES.REMOVE_LOADING });
};
只是一个异步初始化函数,调用时以同步方式执行步骤。
关键是 thunk 可以分派其他 thunks/actions/etc 所以 init thunk 只是分派本身是异步的 getConfig()
操作,所以 init 函数的下一步直到配置 API 调用完成(可能是因为其他一些代码依赖于它)
如果你不想,请不要包装 像这样
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
dispatch(await getConfig());
dispatch({ type: TYPES.REMOVE_LOADING });
};
//this is not using redux-thunk
// Action Creator to get the config object from the API
export const getConfig = async () => {
const res = await tmdbAPI.get('/configuration');
return {
type: TYPES.GET_CONFIG,
payload: res.data,
};
};
重要
但是有很多原因为什么要用 dispatch 包装动作。
举一个例子。
当你想一步一步获取多个数据时
export const getData = () => async dispatch => {
dispatch({
type: DATA_LOADING_START
});
try {
const res = await tmdbAPI.get('/url1');
dispatch({
type: DATA1_LOADED,
payload: res.data,
});
const res = await tmdbAPI.get('/url2');
dispatch({
type: DATA2_LOADED,
payload: res.data,
});
} catch (err) {
// handle error
}
dispatch({
type: DATA_LOADING_END
});
};
//this is using redux-thunk
@AlexanderSolonik
问题: 为什么要通过调度包装动作?
因为dispatch()
将动作结果发送给reducer。