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
相关产品推荐
相关产品推荐

