如果我使用扩展运算符,为什么状态会发生变化?

IT技术 reactjs state
2021-05-24 09:50:52

我有我正在 jsfiddle 上测试的代码

onVote = (dir, index) => {        
    console.log(this.state)

    const products = [...this.state.products]           
    products[index].votes = dir ? products[index].votes + 1 : products[index].votes - 1

    console.log(this.state.products[index].votes)
    // this.setState({products})
  };

https://jsfiddle.net/hkL3wug7/2/

但是,即使我没有设置状态,控制台日志也会显示每次单击加号和减号时状态都会发生变化。

我做了与本文相同的https://medium.com/@giltayar/immutably-setting-a-value-in-a-js-array-or-how-an-array-is-also-an-object -55337f4d6702

const newState = [...state] // clone the array
      newState[action.index].done = true
      return newState

据我所理解

(它不是另一个问题的重复,我不是在寻求一种有效的方法)

2个回答

正如@Carcigenicate 所提到的,您已经创建了数组的浅拷贝,这意味着您有一个指向原始数组中相同对象的新数组。

为避免改变原始对象,您还需要创建要改变的对象的副本,例如:

// Shallow copy of the array
const products = [...this.state.products];

// Shallow copy of the object within the array
const updatedProduct = { ...products[index] };

// Update the copy of the object
updatedProduct.votes = dir ? updatedProduct.votes + 1 : updatedProduct.votes - 1;

// Replace the object with the updated copy
products[index] = updatedProduct;

正如评论中提到的@Carcigenicate,使用扩展运算符创建数组的浅拷贝。这给您带来了问题,因为数组的扩展版本包含Object通过引用传递的 s。因此,即使您的局部变量products是 的新副本this.state.products,它们也都包含对相同Objects 的引用

为了实现您想要做的事情,您必须克隆this.state.products. 一种可能的方法是使用Object.assign并替换const products = [...this.state.products]为:

const products = [
    Object.assign({}, this.state.products.Orange),
    Object.assign({}, this.state.products.Apples),
    Object.assign({}, this.state.products.Bananas)
]