I am trying to copy a state object:
@boundMethod
private _onClickDeleteAttachment(attachmentName: string): void {
console.log("_onClickDeleteAttachment | this.state.requestApproval[strings.Attachments]: ", this.state.requestApproval[strings.Attachments]);
let requestApprovalClone = {... this.state.requestApproval}
if (requestApprovalClone === this.state.requestApproval) {
console.log("they are ===");
}
else {
console.log(" they are not ===");
}
_.remove(requestApprovalClone[strings.Attachments], (attachment: any) => {
return attachment.FileName === attachmentName;
})
console.log("_onClickDeleteAttachment | this.state.requestApproval[strings.Attachments]: ", this.state.requestApproval[strings.Attachments]);
console.log("_onClickDeleteAttachment | requestApprovalClone[strings.Attachments]: ", requestApprovalClone[strings.Attachments]);
}
The state
object is being altered too. From what I have read, I shouldn't mutate a state
object but only change it with setState
.
How can I correct this?
In React, the state is immutable. In simple terms it means that you should not modify it directly. Instead a new object should be created to set the state using setState .
Whenever the data in the state store changes, react will trigger an re-render with the new state which the view consumes and shows it on the screen.
Why Immer works well for React State Immutability? In React, using an Immutable state enables quick and cheap comparison of the state tree before and after a change. As a result, each component decides whether to re-rendered or not before performing any costly DOM operations.
You are getting that behavior, because the
let requestApprovalClone = {... this.state.requestApproval}
is only shallow copying the data, your attachments
property has some nested objects and it keeps the same reference and therefore when changing it, the cloned object gets altered and the state too.
To avoid that, you can perform another copy of your attachments
property like this :
let attachments = [...requestApprovalClone[strings.Attachments]];
_.remove(attachments, function (attachment) {
return attachment.FileName === attachmentName;
});
Changing the attachments variable content won't afftect the state anymore.
you can read more about that behavior here
It has to to with the way that JS handles their const
references.
For those who feel adventerous:
let requestApprovalClone = JSON.parse(JSON.stringify(this.state.requestApproval));
// modify requestApprovalClone ...
this.setState({
requestApproval:requestApprovalClone
})
It would be interesting if Object.assign({},this.state.requestApproval);
is faster than the whole JSON stringify/parse stuff or vice versa
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With