复制React State对象;修改复制的对象更改状态对象

时间:2019-04-02 20:21:51

标签: javascript reactjs

我正在尝试复制状态对象:

@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

state对象也被更改了。根据我的阅读,我不应该突变state对象,而应使用setState对其进行更改。

我该如何纠正?

3 个答案:

答案 0 :(得分:2)

必须与JS处理其const引用的方式有关。

对于那些喜欢冒险的人:

let requestApprovalClone = JSON.parse(JSON.stringify(this.state.requestApproval));

// modify requestApprovalClone ...

this.setState({
  requestApproval:requestApprovalClone
})

如果Object.assign({},this.state.requestApproval);的速度比整个JSON字符串化/解析的速度更快,反之亦然

答案 1 :(得分:1)

您正在得到这种行为,因为

let requestApprovalClone = {... this.state.requestApproval}

仅是浅层复制数据,您的attachments属性具有一些嵌套对象,并且保留相同的引用,因此,在更改它时,克隆的对象也会更改并且状态也会改变。

为避免这种情况,您可以像这样执行attachments属性的另一个副本:

let attachments = [...requestApprovalClone[strings.Attachments]];
_.remove(attachments, function (attachment)  {
  return attachment.FileName === attachmentName;
});

更改附件变量内容将不再影响状态。

您可以了解有关该行为here

的更多信息

答案 2 :(得分:0)

您可以拥有类似的内容:

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