Angular change detection loop triggered by using getters inside template

Discussão em 'Angular' iniciado por d_stack, Outubro 24, 2024.

  1. d_stack

    d_stack Guest

    It seems using getters inside templates causes Angular change detection to go into a loop (getter gets called hundreds of times). After reading up a ton on similar issues out there I cannot seem to get a clear answer.

    Background info:

    I do believe using getters inside the template is the cleanest approach from a maintainability point of view, however seemingly because Angular cannot know if the getter value changed until it calls it, it just calls it all the time. I so far found three alternatives:

    1. Stop using getters, make all properties public and access them directly
    2. Store the value of each getter into a public property on the component and bind that instead of the getter in the template
    3. Change the changeDetection mode of Angular from default to onPush

    Option 1 would seem counterintuitive to the benefit of using Typescript classes. Option 2 would seem like unnecessary code duplication and reduce maintainability, option 3 would require a significant refactoring.

    Here is an example (simplified for illustrative purpose)

    Model:

    export class UserModel {
    private id: string;

    get getId() {
    console.log('Getting id');
    return this.id;
    }
    set setId(id) {
    this.id = id;
    }
    constructor() {
    }
    }


    Component.html

    <h1>Test</h1>
    <p>{{user.getId}}</p>


    Component.ts

    import {Component, OnInit} from '@angular/core';
    import {TestModel} from './test.model';

    @Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
    })
    export class AppComponent implements OnInit {
    public user: UserModel;

    ngOnDestroy() {
    if (this.userObserver) { this.userObserver.unsubscribe(); }
    }

    ngOnInit() {
    this.userObserver = this.userObservable.subscribe(
    (data: UserModel) => {
    this.user = data;
    },
    (err: any) => {
    console.error(err);
    });
    }
    }


    Will output the following console log: console.log output

    Can anyone recommend the best practice to avoid unnecessary loops while working with complex models in Angular? Or even a proper way to debug this type of behavior, as it stands now I am console.logging the getter methods and watching for memmory usage spikes.

    EDIT (Answer) After more time investigating, digging through stack traces I found out the infinite change detection loop was actually being caused by a service we inject called 'Sentry'. Apparently it causes an issue when console.log is used that triggers change detection. Found a github issue about it here: github.com/getsentry/sentry-javascript/issues/1883 Did not find a solution (seems inherently incompatible), will update if I find a fix for it.

    Continue reading...

Compartilhe esta Página