问题
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 Object
s 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 Object
s.
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