基于Redux请求状态变化触发页面跳转或刷新的正确实现方法
Redux Thunk异步请求后跳转的问题修复方案
现有实现的问题
- Thunk未返回请求结果状态:你当前的
acceptProposal异步Thunk没有把请求成功/失败的结果向外暴露,且catch了错误后没有抛出,所以dispatch返回的Promise永远是成功状态,就算接口报错也会进入.then回调。 - 状态获取时机错误:你在
.then中直接读取的isAccepted是组件当前渲染闭包中的旧值,Redux更新状态后需要触发组件重渲染才会拿到新值,和你加不加3秒延时没有必然联系,完全是随机生效。
正确处理方案
方案1:Thunk返回请求结果直接处理(推荐)
直接修改Thunk,将请求的成功/失败状态作为返回值传递给组件,不需要依赖本地状态判断,也不需要加延时。
修改后的Thunk代码:
export const acceptProposal = (id: string) => async ( dispatch: Dispatch<any>, getState: () => RootState, ) => { const {auth} = getState(); const data = { proposalId: id, }; dispatch(actions.acceptProposal()); try { await API.put(`/propostas/change-proposal-status/`, data, { headers: { version: 'v1', 'Content-Type': 'application/json', }, }); dispatch(actions.acceptProposalSuccess()); // 返回成功标识 return { success: true } } catch (error) { dispatch(actions.acceptProposalFailed(error)); // 返回失败标识 return { success: false, error } } };
修改后的组件逻辑:
const acceptProposalHandler = async () => { // 直接拿到Thunk返回的结果 const result = await store.dispatch(acceptProposal(id)) if (result.success) { history.push({ pathname: urls.proposal, state: { starterTab: formatMessage({id: 'proposalList.tabs.negotiation'}), }, }); } };
方案2:监听Redux状态变化触发跳转
如果isAccepted状态本身需要在其他业务逻辑中使用,可以用useEffect监听状态变化,自动触发跳转:
// 从Redux中取isAccepted状态 const isAccepted = useSelector((state: RootState) => state.proposal.isAccepted) useEffect(() => { if (isAccepted) { history.push({ pathname: urls.proposal, state: { starterTab: formatMessage({id: 'proposalList.tabs.negotiation'}), }, }); // 跳转后需重置isAccepted状态,避免重复触发跳转 dispatch(actions.resetAcceptStatus()) } }, [isAccepted, history, formatMessage, dispatch]) const acceptProposalHandler = () => { store.dispatch(acceptProposal(id)) };
注意事项
- 若使用TypeScript,需要给dispatch声明
ThunkDispatch类型,才能正确识别Thunk的返回值类型。 - 方案2必须增加重置状态的逻辑,否则用户返回当前页面时会再次触发跳转。
内容的提问来源于stack exchange,提问作者ncesar
相关产品推荐
相关产品推荐

