简体   繁体   中英

Angular array content changes if condition is both true or false ? Unexpected behavior

I have 3 sibling components in angular. The first one is a sidebar that is calling an API that returns an array of objects. I am populating an unordered list with a bunch of list items with the data that comes back. This component is not relevant to the problem.

Then in the second component I am making a call to a method in a service that makes an API call that returns an object with various properties. Then on a click of a button I am calling another method that is checking if an array contains an object with the same property as the object that came back from the API. If there is no such object, I add it to the array, if there is an object with the given property (id in my case) we do nothing.

As it is too hard to explain the whole process I've tried to reproduce the whole scenario on that stackblitz example .

Go check it, press the first button, then the second one. What I can not understand is why when we click the first button and then the second the object in the array gets updated despite we are checking if the object exists in the array and if it does - we don't even make the call to the method in the service, but it still gets updated somehow. What am I missing here?

@Jason White answer explains what's happening. I would suggest alternative solution. Do not update the object if the condition does not match:

addToSlip(receivedObj, userPick, userPickValue) {
  const found = this.slip.some(el => el.id === this.obj.id);
  console.log(found);
  if (!found) {
    receivedObj.userPick = userPick;
    receivedObj.userPickValue = userPickValue;
    console.log("Not found, we add it to the array!");
    this.service.addToSlip(this.obj);
  } else {
    console.log("Duplicate! We don't add it!");
  }
}

When you call this.service.addToSlip(...) you are passing in a reference to this.obj so when it's added to the array in SlipService , both arrays contain a references to the same object in memory. Updating one will update the other.

Solution is to pass in a new copy into this.service.addToSlip()

// one way
this.service.addToSlip({...this.obj});

// another way (will make a deep copy)
this.service.addToSlip(JSON.parse(JSON.stringify(this.obj)));

Stackblitz: https://stackblitz.com/edit/angular-57xgmd

https://scotch.io/bar-talk/copying-objects-in-javascript

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM