Why is the state mutating if I am using spread operator?

只谈情不闲聊 提交于 2020-02-25 03:59:48

问题


I have this code that I am testing on 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/

However, even though I am not setting State, the console log shows that the state is changes every time I click on the plus and minus signs.

I did the same as in this article 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

as far as I understand

(it is not duplicate of the other question, I am not asking for an efficient way)


回答1:


As @Carcigenicate mentioned, you have created a shallow copy of the array which means you have a new array pointing to the same objects in the original.

To avoid mutating the original object, you will need to also create a copy of the one you would like to mutate, e.g.:

// 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:


As @Carcigenicate mentioned in the comment, using the spread operator creates a shallow copy of the array. This is creating a problem for you because the expanded version of the array contains Objects which are passed by reference. So even though your local variable products is a new copy of this.state.products, they both contain references to the same Objects.

To achieve what you are trying to do, you would have to clone the objects in this.state.products. One possible way to do this is using Object.assign and replace your const products = [...this.state.products] with:

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


来源:https://stackoverflow.com/questions/55987369/why-is-the-state-mutating-if-i-am-using-spread-operator

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!