"expression has changed after it was checked" error despite having the right setup

Discussão em 'Angular' iniciado por derstauner, Abril 22, 2025.

  1. derstauner

    derstauner Guest

    I'm facing the error expression has changed after it was checked. I know, that this check runs only in dev mode (runs twice) and that I won't have the error message in prod. But I want to know why I get this.

    I have a signal-based loader service like this:

    import { Injectable, signal } from '@angular/core';

    @Injectable({ providedIn: 'root' })
    export class LoaderService {
    private _isLoading = signal<boolean>(false);

    get isLoading(): boolean {
    return this._isLoading();
    }

    show() {
    this._isLoading.update(() => true);
    }

    hide() {
    this._isLoading.update(() => false);
    }
    }


    I have also this interceptor:

    import {
    HttpEvent,
    HttpHandler,
    HttpInterceptor,
    HttpRequest,
    HttpResponse,
    } from '@angular/common/http';
    import { Injectable } from '@angular/core';
    import { Observable, catchError, map, throwError } from 'rxjs';
    import { USE_LOADING_SPINNER } from '../constants/app.constants';
    import { LoaderService } from '../../shared/services/loader.service';

    @Injectable()
    export class LoadingInterceptor implements HttpInterceptor {
    constructor(private loaderService: LoaderService) {}

    intercept(
    req: HttpRequest<any>,
    next: HttpHandler
    ): Observable<HttpEvent<any>> {
    if (req.context.get(USE_LOADING_SPINNER)) this.loaderService.show();

    return next.handle(req).pipe(
    map((event: HttpEvent<any>) => {
    if (event instanceof HttpResponse) this.loaderService.hide();
    return event;
    }),
    catchError((error) => {
    this.loaderService.hide();
    return throwError(() => error);
    })
    );
    }
    }


    The USE_LOADING_SPINNER is always set to true, which means I have to mark only the requests where I don't want to have any loading indicator.

    Since the LoaderService is signal-based, I register an effect in the constructor of a component like this:

    constructor() {
    effect(() => {
    this.loading = this.loaderService.isLoading;
    });
    }


    Note the loading variable isnt't a signal, it is a pure boolean variable, since the isLoading method returns a boolean value, not a signal.

    And in the template I have this in a grid component:

    [loading]="loading"


    This setup is working, on initial routing the loading indicator is showing.

    Now I add a refresh method to the component like this:

    refresh() {
    //this.loaderService.show();
    this.gridData$ = this.userService.getUsers();
    //.pipe(tap(() => this.loaderService.hide()));
    }


    But if I click on refresh, I get the error in the topic title and the loading indicator isn't showing. The interceptor gets triggered, I checked this.

    But if I uncomment the calls to the loaderService it works as expected.

    Why do I get this error?

    Continue reading...

Compartilhe esta Página