【问题标题】:Why is the state mutating if I am using spread operator?如果我使用扩展运算符,为什么状态会发生变化?
【发布时间】:2019-09-23 00:53:10
【问题描述】:

我有这段代码在 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

据我所知

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

【问题讨论】:

标签: reactjs state


【解决方案1】:

正如@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;

【讨论】:

    【解决方案2】:

    正如评论中提到的@Carcigenicate,使用扩展运算符会创建数组的浅表副本。这给您带来了一个问题,因为数组的扩展版本包含通过引用传递的Objects。因此,即使您的局部变量 productsthis.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)
    ]
    

    【讨论】:

    • 谢谢。我现在明白了
    猜你喜欢
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 2019-11-27
    • 2022-11-19
    • 1970-01-01
    • 2018-05-17
    相关资源
    最近更新 更多