Answer a question

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

}

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

elsewhere I define s as:

var s={};
   s[this.props.idName] = this.refs.id.value;

This works but I'm wondering if this is the right way to add an element into one of the keys in items. AllItems is really pointing to this.state.items and I thought it should be a deep copy but I'm not sure how to do that.

It seems like items is an object that holds key/value pairs where the value is an array. Is that correct? Where can I go to learn how to manipulate a structure like that?

Answers

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

React社区为您提供最前沿的新闻资讯和知识内容

更多推荐