Angular 2 change detection – refreshing DOM even though nothing has changed

Issue

I have built an application, which is LIVE in beta, and I am now trying to optimize it’s performance. I have a case, where there is a table with images and I noticed that the images keep flickering, which made me look under the hood and I noticed that the DOM keeps refreshing. Refreshing as in, nothing changes, but it keeps deleting and re-adding itself a few times a second.

I figured, I would first log myself into the ngOnChanges(_:SimpleChanges) function, but nothing runs into the console.log from there, meaning that the component itself has not changed, but for some reason, it deems it necessary to refresh it’s DOM.

I’m just wondering, how can I debug this and know, what is causing the component to refresh it’s DOM?

Maybe some tools would help? I tried Augury, but that doesn’t seem to help with performance issues debugging.

PS. Rendering the comopnent in

changeDetection: ChangeDetectionStrategy.OnPush

mode helps a bit (Still don’t understand, why it helps, if OnChanges never runs)… But it does not fully eliminate the DOM refreshing at random moments.

Edit 1

DOM refreshing in console, looks like this
enter image description here

Solution

I found the answer to my own question. My problem was using arrays that are generated by a get method in my template. Aka. there are 2 models: [ParentModel, ChildModel], the ParentModel holds an array of ChildModels. Now I wanted to get only a selection of those ChildModels from the ParentModel and what I did was

class ParentModel {
    __specificChildren() : IChild[] {}
}

and in the template, I used

*ngFor="let child of parentModel.__specificChildren()"

This started refreshing endlessly. Probably because some global events triggered the change detection on the related Models, which created an array with a different pointer each time it was checked, which told Angular that something had changed and thus triggered change detection.

Anyway, how I solved this is, instead of having the function in the template, which was optimal, because I did not want to create an useless variable in the component to complicate things, I still created the helper variable in the component, thus resulting in:

Component

public specificChildren: IChild[]

parentDatatabe.subscribe( _parent {
    this.parent = _parent;
    this.specificChildren = _parent.__specificChildren()
})

Template

*ngFor="let child of specificChildren"

Thus only setting the new children, when the parent database pushes a new value.

Answered By – Karl Johan Vallner

Answer Checked By – Senaida (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.