1

I have a mock array inside of my caseService, from this array data is distributed through the whole web-app.

To get the data inside of another component I use the following code:

this.cases = this.caseService.data;

It works fine, but there's one thing bothering me.

In one of my components I have an infinite scroll:

@HostListener('window:scroll', ['$event'])
scroll() {
  const pos = (document.documentElement.scrollTop || document.body.scrollTop) + document.documentElement.offsetHeight;
  const max = document.documentElement.scrollHeight;
  if (pos === max) {
    this.cases.push(...this.casesService.data);
    // causes trouble
  }
}

As the user scrolls, the array this.cases is being pushed. It works fine, but when I leave this component by going back or routing somewhere else, this.cases & even this.casesService.data keep the amount of entries (amount depends on for how long the user scrolled) - hence every other component displays an increased amount of cases.

Reloading the page solves the issue again.

Tom
  • 3,672
  • 6
  • 20
  • 52
  • 3
    yes because you are modifying the data `this.cases` object inside the directive. and it will be retained across components. what is your expectation – Aravind Jun 25 '19 at 16:53
  • @Aravind Inside of the component with the infinite scroll: I want to push `this.cases` by itself or `this.casesService.data` every time the user reaches a certain scroll position. How can I do so without modifying the data globally? – Tom Jun 25 '19 at 16:55
  • try to pass an `input` to the directive from the component in which you want the infinite scroll to happen – Aravind Jun 25 '19 at 16:56
  • Possible duplicate of [Why does changing an Array in JavaScript affect copies of the array?](https://stackoverflow.com/questions/6612385/why-does-changing-an-array-in-javascript-affect-copies-of-the-array) – Heretic Monkey Jun 25 '19 at 20:10

1 Answers1

1

This happens because this.cases and this.caseService.data are different references to the same object.

To illustrate the issue:

var a = [];
var b = a;
b.push("test");
console.log(a) // ["test"]

To fix this, you need to ensure the two objects are not the same. When you set the initial value, simply clone the array:

this.cases = [...this.caseService.data];

NOTE: There are many ways to clone an array, this is just my personal preference.

Now you can freely modify this.cases without changing this.caseService.data.


As noted by @Rich, this will only prevent changes to the contents of the arrays. This will not prevent changes to properties of these objects.

For example:

var a = [{ name: "Original Name" }];
var b = [...this.caseService.data];
b[0].name = "Test Name";
a[0].name === "Test Name"; // True

To avoid this you would need to perform a deep clone:

this.cases = JSON.parse(JSON.stringify(this.caseService.data));

NOTE: Again, there are many ways to accomplish a deep clone, this is just my personal preference.

Vlad274
  • 6,514
  • 2
  • 32
  • 44
  • 1
    Just a quick note, the spread operator doesn't work for dereferencing nested objects. In that case, you would need to use some other method of deep cloning the object. – Rich Jun 25 '19 at 19:42