Reputation: 19
When I try to change state immutable way in React
, it is changing the state before I call setstate
, which confused me for 3 days now.
This is the method I call in the onClick
event:
share = (indexFolder) => {
console.log(this.state.folderInfo);
const updateFolderInfo = [...this.state.folderInfo];
updateFolderInfo[indexFolder].isProcessing = false;
//state**is already changed**strong text** when console **
console.log(this.state.folderInfo);
this.setState({
folderInfo : updateFolderInfo,
})
// the setState call do not take effect here
}
This is where the method is executed:
<Folder key={folder._id}
sharing={this.state.folderIsProcessing}
folder={folder}
delete={() => this.delete(index)}
share={() => this.share(index)} />
//I'm passing share function as props in here ^ , and use it on
//click event in the Folder component .
Any suggestions why this is happening?
Upvotes: 1
Views: 106
Reputation: 81
The problem here is that by doing const updateFolderInfo = [...this.state.folderInfo];
you are effectively making a shallow copy of folderInfo
.
What that means is that, if you modify any item inside updateFolderInfo
that is an object or an array, you will also be modifying the same object/array inside the original folderInfo
array.
Assuming folderInfo
has only JSON inside, here's a potential solution using JSON.stringify
and JSON.parse
to create a deep copy:
share = indexFolder => {
const updatedFolderInfo = JSON.parse(JSON.stringify(this.state.folderInfo));
updatedFolderInfo[indexFolder].isProcessing = false;
this.setState({ folderInfo : updatedFolderInfo });
}
Here's a tiny example of show you what you are currently doing in a simplified way:
array1 = [{id: 1}, {id: 2}, {id: 3}]
array2 = [...array1]
array2[0].id = 100
array2
// [{id: 100}, {id: 2}, {id: 3}]
array1
// [{id: 100}, {id: 2}, {id: 3}]
You can find more info on shallow vs deep cloning here.
Upvotes: 1
Reputation: 819
Too few information provided, but try to use setState in other way:
share = (indexFolder) => {
this.setState((prevState) => {
const updateFolderInfo = [...prevState.folderInfo];
updateFolderInfo[indexFolder].isProcessing = false;
return {
folderInfo : updateFolderInfo
}
})
}
About async nature of setState: https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3
Upvotes: 0
Reputation: 1893
You are already binding the function to the scope above. Try changing it like this.
share = (indexFolder) => {
console.log(this.state.folderInfo);
const updateFolderInfo = [...this.state.folderInfo];
updateFolderInfo[indexFolder].isProcessing = false;
//state**is already changed**strong text** when console **
console.log(this.state.folderInfo);
this.setState({
folderInfo : updateFolderInfo,
})
// the setState call do not take effect here
}
<Folder key={folder._id}
sharing={this.state.folderIsProcessing}
folder={folder}
delete={this.delete(index)}
share={this.share(index)}
/>
Upvotes: 0