7

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]);
}

enter image description here

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?

3 Answers 3

8

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

Sign up to request clarification or add additional context in comments.

Comments

5

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

1 Comment

gute Antwort Gabriel
1

You can have something like:

let requestApprovalClone = Object.assign({},this.state.requestApproval);

requestApprovalClone.strings.Attachments = requestApprovalClone.strings.Attachments.slice(); // will create a shallow copy of this array as well

_.remove(requestApprovalClone[strings.Attachments], (attachment: any) => {
        return attachment.FileName === attachmentName;
    })

this.setState({
  requestApproval:requestApprovalClone
})// If you want to update that in state back

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.