You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置空依赖数组的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 03:15:03