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

React Hooks useEffect中setInterval操作数组状态非预期增长求解

问题原因

这是React 18开发环境下的预期行为,不是Hooks的Bug:

  • 本地开发时默认开启了严格模式(StrictMode),该模式会在开发环境主动调用两次状态更新函数,用于提前排查更新逻辑中存在的副作用问题,生产环境不会触发该逻辑,所以你的静态站点运行正常。
  • 你的更新代码存在不符合immutable规范的问题:在setA的回调函数中直接修改了传入的原状态prev的内部值,第一次调用更新函数就已经修改了原状态的内容,第二次调用时会在已经修改后的值基础上再次+100,最终表现为每秒增加200。

解决方案

不需要使用useReducer,只要修改状态更新逻辑,遵循不修改原状态、先拷贝再修改的原则即可,修改后的代码如下:

定时器部分修改

useEffect(() => {
  const eff = setInterval(() => {
    setA((prev) => {
      // 先完整拷贝二维数组,不改动原prev
      const newA = prev.map(subArr => [...subArr])
      newA[1][0] += 100;
      console.log("add 100");
      return newA;
    });
  }, 1000);
  return () => clearInterval(eff);
}, []);

点击事件逻辑说明

你给出的multiple函数本身没有修改传入的原状态p,而是直接计算生成了全新的二维数组,本身是符合规范的,只需要把多余的展开操作去掉即可(也可以保留,不影响运行):

const multiple = () => {
  setA((p) => {
    const newArray = [
      [
        p[0][0] * p[0][0] + p[0][1] * p[1][0],
        p[0][0] * p[0][1] + p[0][1] * p[1][1],
      ],
      [
        p[1][0] * p[0][0] + p[1][1] * p[1][0],
        p[1][0] * p[0][1] + p[1][1] * p[1][1],
      ],
    ];
    // newArray本身就是全新数组,不需要再展开生成新数组
    return newArray;
  });
};

修改完成后不管严格模式调用几次更新函数,最终的状态更新结果都是一致的,就会符合你每秒加100的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:42:03