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

React中依赖为空的useEffect导致列表重复项的解决方法

修复React列表重复数据问题

核心问题分析

  1. React 18严格模式触发重复执行:开发环境下,React 18的严格模式会让useEffect执行两次,导致整个数据获取流程重复触发,最终数据翻倍。
  2. 异步状态更新时序冲突:setProducts([])是异步操作,后续的子fetch请求回调可能在列表清空完成前就开始执行,或者两次流程的请求同时往列表中追加数据,最终造成重复。

具体修复方案

方案1:批量请求+请求取消(推荐)

改用Promise.all批量处理所有子请求,一次性更新状态,同时用AbortController取消未完成的请求,避免重复执行带来的问题:

const [products, setProducts] = useState([]);

useEffect(() => {
  const abortController = new AbortController();
  const signal = abortController.signal;

  fetch('http://localhost:1234/', { signal })
    .then((response) => response.json())
    .then((data) => {
      const productPromises = [];
      const maxItems = Math.min(10, data['products'].length);
      // 收集所有子请求的Promise
      for(let i = 0; i < maxItems; i++) {
        productPromises.push(
          fetch(`http://localhost:1234/lookup/${data['products'][i]}`, { signal })
            .then(res => res.json())
        );
      }
      // 等待所有请求完成后一次性更新状态
      Promise.all(productPromises)
        .then(results => {
          setProducts(results);
        })
        .catch(err => {
          if (err.name !== 'AbortError') console.error(err);
        });
    })
    .catch(err => {
      if (err.name !== 'AbortError') console.error(err);
    });

  // 清理函数:组件卸载或effect重新执行时取消所有未完成请求
  return () => abortController.abort();
}, []);

方案2:临时关闭严格模式(仅开发环境验证用)

如果是开发环境严格模式导致的重复执行,可以暂时在项目入口文件(如index.js)中去掉<React.StrictMode>标签,但不推荐长期使用——严格模式能帮你提前发现潜在的组件问题。

关键优化点

  • 批量更新状态:避免多次调用setProducts追加数据,改用Promise.all一次性替换整个列表,彻底消除异步状态更新的时序冲突。
  • 请求生命周期管理:用AbortController确保组件卸载或重复渲染时,旧请求会被取消,不会再触发状态更新。
  • 减少不必要的异步操作:去掉单独的setProducts([]),直接用请求结果覆盖列表,避免额外的异步清空步骤。

内容的提问来源于stack exchange,提问作者Femn Dharamshi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 12:35:19