React路由来回切换未触发POST请求显示旧数据如何解决
问题根因
useEffect传入空依赖数组[],逻辑仅在组件首次挂载时执行。路由跳转返回时如果组件被复用(路由缓存/React组件复用机制),请求逻辑不会再次触发。- 请求触发条件错误:用
Object.keys(paymentInfoData).length === 0作为请求前置判断,首次进入A保单后数据存入全局Context,返回列表页时Context数据未清空,再次进入B保单时判断条件不成立,直接跳过请求逻辑。 - 未绑定保单唯一标识作为触发依赖:现有逻辑没有关联当前访问的保单ID,只要Context有残留数据就直接复用,必然出现不同保单数据串显的问题。
修复方案
- 调整页面卸载逻辑:离开支付页时清空Context中存储的保单支付数据,从根源避免旧数据残留。
- 修正useEffect依赖项:将当前保单的唯一标识(保单号+续保号的组合值)加入依赖数组,只要路由携带的保单信息变化,就自动重新触发请求,移除「Context无数据才请求」的错误判断。
- 请求前重置状态:发起新保单请求前先清空旧数据,避免加载过程中短暂显示上一保单的内容。
修改后的组件代码如下:
const { paymentInfoData, setPaymentInfoData } = useContext(PaymentInfoDataContext); const currentPolicy = props.location.state.policy; // 生成保单唯一标识,作为effect触发依赖 const policyUniqueKey = `${currentPolicy.policyNumber}_${currentPolicy.renewalNumber}`; // 组件卸载时清空全局Context残留数据 useEffect(() => { return () => setPaymentInfoData({}); }, []); // 切换保单时自动重新拉取数据 useEffect(() => { if (currentPolicy.isActive !== true) return; // 请求前清空旧数据,避免串显 setPaymentInfoData({}); PolicyService.getAsosInstallments({ policyNumber: currentPolicy.policyNumber, renewalNumber: currentPolicy.renewalNumber, policyTypeExtCode: currentPolicy.policyType.extCode, productTypeExtCode: currentPolicy.productType.extCode }).subscribe(response => { setPaymentInfoData(response); }); }, [policyUniqueKey, currentPolicy.isActive]);
可选优化
现有service层手动包装Observable的写法可以简化,直接用rxjs的from操作符转换axios Promise即可,还能自动兼容rxjs的取消订阅逻辑,避免组件卸载后请求返回修改状态导致的内存泄漏:
import { from } from 'rxjs'; const getAsosPaymentInfo = (getPolicyAccountInfoRequestDto) => { return from( axiosInstance .post(SERVICE_PATH + '/getAsosPaymentInfo', getPolicyAccountInfoRequestDto) .then(res => res.data) ); };
注意:如果项目中对路由页面做了keep-alive缓存配置,组件不会在路由跳转时卸载重建,空依赖的useEffect永远只执行一次,必须通过路由参数/状态的变化作为依赖触发请求,不能依赖组件挂载时机。
内容的提问来源于stack exchange,提问作者jron
相关产品推荐
相关产品推荐

