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

React17开发模式下useState函数式更新出现意外状态不一致问题

问题根源

这个问题是 React 17 开发模式下 <StrictMode> 严格模式的特性导致的,你的 useState 写法本身没有语法错误。

React 17 的严格模式为了提前检测出代码中不符合规范的副作用,在开发环境会故意两次调用 useState 的函数式更新回调,且两次调用传入的 prev 状态都是更新前的旧值,最终会采用第二次调用返回的结果作为实际要更新的状态。

你把 Date.now() 这种每次执行结果都会变化的非纯逻辑写在了更新回调内部,第一次调用回调时生成了 id 1636301326611,间隔1ms后第二次调用回调又生成了id 1636301326612,第一次的返回结果被直接丢弃,实际状态更新为第二次的 1636301326612,就出现了你看到的日志中id异常跳变的情况。

其他现象解释

  • 生产环境无法复现:严格模式的二次调用逻辑只在开发环境生效,生产构建时会被自动移除。
  • 直接传对象没有问题:直接传对象的场景下,新状态值是在 setState 调用前就生成完成的,不管更新逻辑被调用多少次,传入的都是同一个状态对象,不会出现值不一致的问题。

修复方案

保证 useState 的函数式更新回调是纯函数,不要在回调内部执行会产生可变结果的逻辑,把这类逻辑移到回调外部即可:

const update = () => {
  // 把可变值的生成移到回调外部
  const id = Date.now();
  setState(prev => {
    console.log('previous id:', prev.id, 'new id:', id);
    return {
      id,
    };
  });
};

修改后不管回调被调用几次,使用的id都是同一个值,不会再出现状态和预期不符的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:54:00