配置空依赖数组的useEffect 点击浏览器返回按钮后展示重复产品
问题根因
- React 18 开发环境默认开启严格模式,组件首次挂载会执行两次完整的挂载流程,你写的空依赖useEffect会触发两次
fetchProducts请求。如果你的状态更新逻辑是把接口返回的产品数据拼接到原有列表后,两次结果累加就会出现双倍数据。这个问题在生产环境关闭严格模式后不会复现,但建议从业务逻辑层面修复。 - 你用的路由方案切换页面时没有销毁当前组件实例,或者全局状态(Redux/Context等)存储的产品列表没有在组件卸载时清空,点击返回后组件重新挂载,useEffect再次触发请求,新数据拼到旧数据之后也会导致数量翻倍。
修复方案
1. 修改状态更新逻辑(最推荐)
把产品列表的状态更新从拼接改为全量覆盖,每次接口返回结果直接替换原有列表,从根源避免重复累加:
// 原有错误的拼接逻辑示例 case 'FETCH_PRODUCTS_SUCCESS': return { ...state, products: [...state.products, ...action.payload] } // 修改为覆盖逻辑 case 'FETCH_PRODUCTS_SUCCESS': return { ...state, products: action.payload }
2. 给useEffect加清理逻辑
如果你的业务场景需要在组件卸载时清空产品列表,或者需要中断未完成的请求,可以加清理函数:
useEffect(() => { const abortController = new AbortController(); // 把终止信号传给fetch请求,卸载时直接中断未完成的请求 dispatch(fetchProducts(abortController.signal)); return () => { abortController.abort(); // 可选:卸载时清空全局存储的产品列表 dispatch(clearProductsList()); } }, [dispatch]);
3. 加请求前置判断
可以通过加载状态、现有列表长度做判断,避免重复触发请求:
useEffect(() => { // 只有没有加载中、且产品列表为空时才触发请求 if (!loading && products.length === 0) { dispatch(fetchProducts()); } }, [dispatch, loading, products.length]);
内容的提问来源于stack exchange,提问作者Cláudio Vitor Dantas
相关产品推荐
相关产品推荐

