Right way to clone objects / arrays during setState in React

前端 未结 4 1351
温柔的废话
温柔的废话 2021-02-20 10:36

I start with:

constructor() {
   super();
      this.state = {
         lists: [\'Dogs\',\'Cats\'], 
         items: {Dogs: [{name: \"Snoopy\"}, {name: \"Lola\"         


        
4条回答
  •  长情又很酷
    2021-02-20 11:30

    I personally rely on this deep copy strategy. JSON.parse(JSON.stringify(object)) rather than spread operator because it got me into weird bugs while dealing with nested objects or multi dimensional arrays.

    spread operator does not do a deep copy if I am correct and will lead to state mutations with NESTED objects in React.

    Please run through the code to get a better understanding of what is happening between the two. Imagine that is the state variable that you mutate using spread operator.

    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

    Now, if you wanted to do a deep copy on your object change the handler to this

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

提交回复
热议问题