Right way to clone objects / arrays during setState in React

DCR*_*DCR 5 javascript reactjs

I start with:

constructor() {
   super();
      this.state = {
         lists: ['Dogs','Cats'], 
         items: {Dogs: [{name: "Snoopy"}, {name: "Lola"}, {name: "Sprinkles"}], 
                 Cats: [{name: "Felidae"}, {name: "Garfiled"}, {name: "Cat in the Hat"}] }             
   };

}
Run Code Online (Sandbox Code Playgroud)

then I have my addItem function:

handleAddItem(s) {      

  var key = Object.keys(s)[0];
  var value = s[key];

  var allItems = {...this.state.items};

      allItems[key].push({name: value});    

      this.setState({items: allItems});
}
Run Code Online (Sandbox Code Playgroud)

elsewhere I define s as:

var s={};
   s[this.props.idName] = this.refs.id.value;
Run Code Online (Sandbox Code Playgroud)

这可行,但我想知道这是否是将元素添加到项中的键之一的正确方法。AllItems确实指向this.state.items,我认为它应该是深层副本,但我不确定如何做到这一点。

似乎items是一个包含键/值对的对象,其中值是一个数组。那是对的吗?我在哪里可以学习如何操纵这样的结构?

Nan*_*ndi 14

我个人依靠这种深层复制策略。 JSON.parse(JSON.stringify(object))而不是spread运算符,因为它在处理嵌套对象或多维数组时使我陷入了奇怪的错误中。

spread如果我正确的话,operator不会进行深层复制,这会导致React中的NESTED对象导致状态突变。

请遍历代码以更好地了解两者之间正在发生的事情。想象一下,这是您使用spread运算符进行变异的状态变量。

const obj = {Dogs: [{name: "Snoopy"}, {name: "Lola"}, {name: "Sprinkles"}], Cats: [{name: "Felidae"}, {name: "Garfiled"}, {name: "Cat in the Hat"}] };

const newObj = {...obj};
console.log("BEFORE SPREAD COPY MUTATION")

console.log("NEW OBJ: " + newObj.Dogs[0].name); //Snoopy
console.log("OLD OBJ: " + obj.Dogs[0].name); //Snoopy

newObj.Dogs[0].name = "CLONED Snoopy";

console.log("AFTER SPREAD COPY MUTATION")

console.log("NEW OBJ: " + newObj.Dogs[0].name); // CLONED Snoopy
console.log("OLD OBJ: " + obj.Dogs[0].name); // CLONED Snoopy

// Even after using the spread operator the changed on the cloned object are affected to the old object. This happens always in cases of nested objects.

// My personal reliable deep copy

console.log("*********DEEP COPY***********");

console.log("BEFORE DEEP COPY MUTATION")
deepCopyObj = JSON.parse(JSON.stringify(obj));


console.log("NEW OBJ: " + newObj.Dogs[0].name); //CLONED Snoopy
console.log("OLD OBJ: " + obj.Dogs[0].name); // CLONED Snoopy
console.log("DEEP OBJ: " + deepCopyObj.Dogs[0].name); //CLONED Snoopy


deepCopyObj.Dogs[0].name = "DEEP CLONED Snoopy";

console.log("AFTER DEEP COPY MUTATION")
console.log("NEW OBJ: " + newObj.Dogs[0].name); // CLONED Snoopy
console.log("OLD OBJ: " + obj.Dogs[0].name); // CLONED Snoopy
console.log("DEEP OBJ: " + deepCopyObj.Dogs[0].name); // DEEP CLONED Snoopy
Run Code Online (Sandbox Code Playgroud)

现在,如果您想对对象进行深层复制,请将处理程序更改为此

handleAddItem(s) {      

  var key = Object.keys(s)[0];
  var value = s[key];

  var allItems = JSON.parse(JSON.stringify(this.state.items));

      allItems[key].push({name: value});    

      this.setState({items: allItems});
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这可能会导致数据丢失。例如日期。 (2认同)