为什么useState钩子在不调用另一个对象的情况下更改了另一个对象?

问题描述 投票:0回答:1

我有一个React组件,它在首次加载时会检索数据。


const [data, setDate] = useState(null);
const [originalData, setOriginalData] = useState(null);

useEffect(() => {
    async function fn() {
      let res = await getObject();
      setData({...res});
      setOriginalData({...res});
    }

    fn();
}, [])

我调用2个不同的挂钩来设置dataoriginalData状态。

这样做的目的是使我拥有可以用于组件中某些逻辑的不变版本的数据。

但是,当我更改为data状态时,似乎也正在更改originalData状态,而无需我进行任何调用。

const change() => {
    let updatedData = {...data};
    updatedData.someProperty = 'newValue';
    setData(updatedData);
}

我本来希望数据现在包含值为someProperty的属性newValue,并且originalData在初始加载后将保持不变。

但是当我比较它们时,dataoriginalData现在都具有someProperty

有人能指出我正确的方向吗?

编辑:添加点差运算符

reactjs react-hooks
1个回答
0
投票

问题:相同的参考

更改data更改originalData的原因不是因为React钩子,而是因为对象在JavaScript中的行为方式。尽管dataoriginalData不同,但它们仍指的是同一对象(来自res)。 因此,对其中任何一个所做的任何更改都会反映在另一个上,因为它们具有相同的引用。

解决方案:克隆

因此,您应该克隆数据,而不是直接分配它们。

// JSON 
const originalData = JSON.parse(JSON.stringify(res))

// Object.assign
const originalData = Object.assign({}, res)

// Or spread opr
const originalData = { ...res }

// Then set the state
setOriginalData(originalData);

ES6方法,如Object.assign和spread运算符会进行浅表复制。如果您需要深层副本,并且您的数据中没有日期,函数,未定义,Infinity,RegExps,地图,集合,Blob,FileList,ImageData,稀疏数组,类型数组或其他复杂类型,请使用JSON解析,字符串化。

查看此question了解有关在JavaScript中进行克隆的更多详细信息

© www.soinside.com 2019 - 2024. All rights reserved.