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

Immer非状态来源数据被Draft:为何baseState与nextState不相等?

关于Immer中baseState与nextState不全等的问题解析

问题背景

根据Immer官方文档,非状态来源的数据不会被Draft处理,但实际测试中出现了与预期不符的情况:

示例代码:

import produce from "immer";

let baseState = {
  value: { x: 1 },
  t: "a",
};

let someVal = { x: 2 };
let nextState = produce(baseState, (draft) => {
  draft.value = someVal;
  draft.value.x = 1;
});

console.log("baseState", JSON.stringify(baseState));
console.log("nextState", JSON.stringify(nextState));
console.log("isEqual", baseState === nextState); // 输出false

原本预期baseState与nextState引用全等,但实际比较结果为false,需明确原因。

核心原因解析

  • Immer的状态更新触发逻辑:Immer判断是否生成新状态的关键是「draft对象的结构是否被修改」。当执行draft.value = someVal时,已经对draft的value属性完成赋值操作,Immer会立即标记顶层状态需要更新,最终生成一个全新的顶层对象作为nextState。
  • 非状态数据的Draft规则误区:官方文档提到的「非状态来源的数据不会被Draft」,指的是外部对象someVal本身不会被转化为Draft副本——修改draft.value.x时,实际直接操作的是原始的someVal,而非它的临时Draft对象。但这和顶层状态是否生成新对象是两个独立逻辑:只要修改了draft的属性(哪怕是赋值外部对象),Immer就会创建新的顶层状态对象。
  • 全等比较的本质:===运算符比较的是对象的内存引用。baseState是初始创建的原始对象,nextState是Immer新生成的顶层对象,两者内存地址不同,因此比较结果为false。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 05:20:03