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

React StrictMode下useEffect与setInterval重复执行问题求解

解决StrictMode下useEffect定时器导致状态异常的问题

你的问题核心是直接修改React状态对象引发的异常,加上StrictMode在开发环境的双重渲染放大了这个问题。StrictMode的双重执行是开发环境的检测机制,生产环境不会触发,但我们需要让代码在开发环境也能正常工作,关键是修复状态不可变的问题。

原代码的问题点

在setQueueState的回调中,你直接修改了pre数组里的line[0].items:

line[0].items = line[0].items > 0 ? line[0].items - 1 : 0;

这违反了React状态不可变的原则——状态对象是只读的,直接修改会导致React无法正确追踪状态变化,在StrictMode的双重渲染下,这种突变会导致状态更新叠加,出现物品数量一次减2的情况。

修复后的代码

下面是遵循状态不可变原则的修改版本:

useEffect(() => {
  const interval = setInterval(() => {
    setQueueState((prev) => {
      return prev.map((line) => {
        if (line.length === 0) return [];
        
        // 创建新的首位人员对象,不修改原状态
        const updatedFirst = {
          ...line[0],
          items: line[0].items > 0 ? line[0].items - 1 : 0
        };

        if (updatedFirst.items > 0) {
          // 组合新数组:更新后的首位 + 过滤后的后续人员
          return [
            updatedFirst,
            ...line.slice(1).filter(person => person.items > 0)
          ];
        } else {
          // 移除首位,保留过滤后的后续人员
          return [...line.slice(1).filter(person => person.items > 0)];
        }
      });
    });
  }, 4000);

  return () => clearInterval(interval);
}, []);

修复说明

  1. 状态不可变处理:每次更新状态时,都创建新的对象(updatedFirst)和数组,完全不修改原有的prev状态对象,确保React能正确识别状态变化。
  2. StrictMode兼容性:修复后,即使StrictMode在开发环境双重执行useEffect,最终只会保留一个定时器,且状态更新逻辑是纯函数式的,不会出现叠加异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:23:18