Angular Zoneless: Changing property value for an object-based signal unexpectedly updates the...

Discussão em 'Angular' iniciado por Lukas S., Outubro 23, 2024.

  1. Lukas S.

    Lukas S. Guest

    I have an Angular v18.2 application that uses zoneless change detection:

    export const appConfig: ApplicationConfig = {
    providers: [provideExperimentalZonelessChangeDetection(), provideRouter(routes)]
    };


    The zone.js polyfill has also been removed from angular.json.

    I have a counter component that uses an object as a signal:

    counter.component.ts:

    interface CounterModel {
    value: number
    }

    @Component({
    selector: 'app-counter',
    standalone: true,
    imports: [],
    templateUrl: './counter.component.html',
    styleUrl: './counter.component.scss',
    changeDetection: ChangeDetectionStrategy.OnPush
    })
    export class CounterComponent {
    counterModel: WritableSignal<CounterModel> = signal({
    value: 0
    })

    increment() {
    this.counterModel().value++
    }

    decrement() {
    this.counterModel().value--
    }
    }


    counter.component.html:

    <p>{{ counterModel().value }}</p>
    <button (click)="decrement()">Decrement</button>
    <button (click)="increment()">Increment</button>


    Note the increment and decrement methods simply update the value property of the object. They do NOT change the object reference for the signal. Given this, I would expect that change detection would not run, and the view would not update when clicking the Decrement/Increment buttons.

    However, contrary to my expectations, the view DOES update. Why is that? Clearly there is something about zoneless change detection and signals that I am not understanding.

    Also, is this behavior something that I can safely rely on? Or would it be better to update the CounterModel.value property to use a nested signal, or else create a new instance of CounterModel in the increment and decrement methods? Would appreciate any guidance regarding best practices here.

    Continue reading...

Compartilhe esta Página