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

React中使用Object.assign处理state未达预期问题排查

为什么你的prevGeoJson和geoJson最后完全相同?

嘿,我来帮你理清楚这个问题——你猜的没错,确实是Object.assign的特性导致的,但核心原因是它只做浅拷贝,我们一步步拆解:

首先看你的代码逻辑:你想先把当前的geoJson存到prevGeoJson里,再修改新的geoJson,最后更新状态。但Object.assign({}, this.state.geoJson)只会复制geoJson的第一层属性,而geoJson.features是一个数组(引用类型),所以prevGeoJson.features和geoJson.features指向的是同一个数组对象。

当你执行geoJson.features.push(data)的时候,你其实是在修改这个共享的数组——那prevGeoJson.features自然也会跟着变,最后两个对象看起来就完全一样了,这可不是你想要的“捕获时刻M的状态”效果。

那怎么解决呢?我们需要对嵌套的引用类型也做拷贝,确保prevGeoJson和geoJson的features是两个独立的数组,这里给你几个实用的方案:


方案1:手动拷贝嵌套数组(最直接)

既然问题出在features数组,我们单独复制它就行,用ES6的扩展运算符很方便:

// 复制原geoJson的同时,单独复制features数组,确保prevGeoJson拿到的是时刻M的状态
const prevGeoJson = {
  ...this.state.geoJson,
  features: [...this.state.geoJson.features]
};

// 直接创建带新数据的geoJson,同样复制数组并添加新元素
const geoJson = {
  ...this.state.geoJson,
  features: [...this.state.geoJson.features, data]
};

this.setState({
  prevGeoJson,
  geoJson,
  currentMarker: data
});

这样prevGeoJson.features和geoJson.features就是两个完全独立的数组,修改其中一个不会影响另一个。

方案2:JSON序列化深拷贝(适合简单结构)

如果你的geoJson里没有函数、Symbol这类无法被JSON序列化的内容,这种方式可以快速实现深拷贝:

// 用JSON序列化再反序列化,彻底复制整个对象
const prevGeoJson = JSON.parse(JSON.stringify(this.state.geoJson));
const geoJson = JSON.parse(JSON.stringify(this.state.geoJson));

geoJson.features.push(data);

this.setState({
  prevGeoJson,
  geoJson,
  currentMarker: data
});

注意:如果对象里有循环引用、函数或者特殊类型,这种方法会丢失这些内容,所以只适合结构简单的场景。

方案3:用不可变数据库(复杂项目推荐)

如果你的项目经常需要处理这类状态更新,推荐用Immer或者Immutable.js,它们能让你用“看起来可变”的写法,实际生成不可变的状态,避免手动拷贝的麻烦。比如用Immer的话:

import produce from 'immer';

this.setState(produce(draft => {
  // 先复制当前geoJson到prevGeoJson
  draft.prevGeoJson = JSON.parse(JSON.stringify(draft.geoJson));
  // 直接修改draft里的geoJson,Immer会帮你生成新的不可变对象
  draft.geoJson.features.push(data);
  draft.currentMarker = data;
}));

当然这个需要额外安装依赖,适合状态结构复杂的项目。


总结一下:核心问题就是浅拷贝导致嵌套的引用类型共享内存,只要确保嵌套的数组/对象也被复制成独立实例,就能解决这个问题啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:26:08