React中修改赋值变量致原state更新?求解决方案
React状态意外同步更新的原因与解决方法
原因
你遇到的问题本质是JavaScript引用类型的浅拷贝导致的:
- 用
[...formData.mappedColumns]复制数组时,这只是浅拷贝——它仅复制了数组本身的结构,但数组内的每个对象仍和原状态中的对象指向同一个内存地址。 - 当你修改
mappingConfig[mIndex].source这类对象属性时,实际上是直接修改了原状态formData.mappedColumns里对应对象的内容,因为二者共享同一个引用。
解决方法
要避免这种情况,需要对数组里的每个对象也进行深拷贝,切断与原状态对象的引用关联,再通过React的setFormData方法正确更新状态。
方法1:遍历数组并复制每个对象(推荐)
使用map遍历数组,对每个对象用对象扩展运算符{...item}或Object.assign({}, item)创建新对象,实现针对对象第一层属性的深拷贝:
const [formData, setFormData] = useState({ mappedColumns: [ { source: "MAIN SOURCE", target: "MAIN TARGET", transformationValue: "MAIN VALUE" } ] }); // 修改状态的逻辑 const updateMapping = () => { const targetIndex = 0; // 深拷贝数组中的每个对象 let mappingConfig = formData.mappedColumns.map(item => ({ ...item })); const mIndex = mappingConfig.findIndex(p => p.target === targetIndex); // 确保找到对应项再修改 if (mIndex !== -1) { mappingConfig[mIndex].source = 'source'; mappingConfig[mIndex].transformationValue = 'value'; // 更新状态,遵循不可变性原则 setFormData(prevState => ({ ...prevState, mappedColumns: mappingConfig })); } };
方法2:使用JSON序列化(简单但有局限性)
如果对象里没有函数、Symbol、日期等特殊类型,可以用JSON.parse(JSON.stringify())实现完全深拷贝:
let mappingConfig = JSON.parse(JSON.stringify(formData.mappedColumns));
注意:这种方法会丢失函数、Symbol等无法被JSON序列化的类型,仅适用于纯数据对象的场景。
关键注意点
- React状态更新必须遵循不可变性原则:永远不要直接修改原状态对象,而是创建新的对象/数组后,通过
setState方法更新。 - 浅拷贝仅适用于一维数组/纯值类型的对象,嵌套对象或数组必须用深拷贝切断引用。
内容的提问来源于stack exchange,提问作者Rajitha Ganji IN
相关产品推荐
相关产品推荐

