Understanding change detection
The secret sauce to Angular’s reactivity and performance is in its change detection strategies and the creative application of those strategies. Change detection is an important mechanism for ensuring the application view stays in sync with the underlying data models, and can respond appropriately when there are changes to these data models.
Disclaimer: Angular has introduced changes to its change detection mechanism in versions 16 and 17.
Change Detection Strategies in Angular
Whenever data changes, Angular needs to reflect those changes in the view. This process involves checking the current value of a templates’ expressions against their previous values. If any differences are detected, Angular updates the view accordingly with the new values.
Angular implements two primary strategies for change detection:
- Default (CheckAlways): Angular checks for changes in bindings during every component tree check, starting from the root component down to child components.
- OnPush: Angular performs change detection only on components that have received new reference types, or when explicitly triggered.
Example: Default Change Detection Strategy
Let’s illustrate the default change detection with a simple component:
import { Component } from '@angular/core';
@Component({
selector: 'app-change-detection-example',
template: `<p>{{counter}}</p>
<button (click)="increment()">Increment</button>`
})
export class AppComponent {
counter = 0;
increment() {
this.counter++;
}
}
In this example, every click on the “Increment” button calls the increment
method, which updates the counter
property. Angular will periodically run a change detection cycle and will detect that this variable has been changed, it will then update the paragraph text in the view with the new counter
value.
Similarly let’s illustrate the OnPush
change detection strategy with a similar component that also displays a counter. This component will only update its view when the counter
property, marked as an input, receives a new value.
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-onpush-example',
template: `<p>Counter: {{counter}}</p>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CounterDisplayComponent {
@Input() counter: number;
}
By setting the changeDetection
strategy to OnPush
, this component optimizes performance by limiting change detection runs. Angular will only update the view for this component when the counter
input changes, rather than checking for changes with every interaction or change detection cycle in the application. This approach is particularly useful for components that rely on inputs and do not change frequently, as it helps to minimize unnecessary rendering and improve app performance.
Conclusion
Angular’s change detection mechanism is a fundamental aspect of the framework, ensuring that applications are both reactive and performant.
Attribution
Image by rawpixel.com on Freepik