How to Use OnPush Change Detection in Angular for Better Performance
Use
ChangeDetectionStrategy.OnPush in your Angular component decorator to tell Angular to check for changes only when input properties change or events occur. This improves performance by skipping checks when data hasn't changed.Syntax
Set the changeDetection property in the @Component decorator to ChangeDetectionStrategy.OnPush. This tells Angular to run change detection only when the component's inputs change or an event inside the component happens.
@Component: Decorator to define a component.changeDetection: Property to set the detection strategy.ChangeDetectionStrategy.OnPush: Strategy to optimize checks.
typescript
import { Component, ChangeDetectionStrategy } from '@angular/core'; @Component({ selector: 'app-example', template: `<p>{{ data }}</p>`, changeDetection: ChangeDetectionStrategy.OnPush }) export class ExampleComponent { data = 'Hello OnPush'; }
Output
<p>Hello OnPush</p>
Example
This example shows a parent component passing data to a child component using OnPush. The child updates only when the input changes, improving performance by avoiding unnecessary checks.
typescript
import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; @Component({ selector: 'app-child', template: `<p>Child data: {{ data }}</p>`, changeDetection: ChangeDetectionStrategy.OnPush }) export class ChildComponent { @Input() data!: string; } @Component({ selector: 'app-parent', template: ` <button (click)="updateData()">Update Data</button> <app-child [data]="parentData"></app-child> ` }) export class ParentComponent { parentData = 'Initial'; updateData() { this.parentData = 'Updated ' + new Date().toLocaleTimeString(); } }
Output
Button labeled 'Update Data' and below it text 'Child data: Initial' initially, changing to 'Child data: Updated HH:MM:SS' after button clicks
Common Pitfalls
Common mistakes include:
- Mutating objects or arrays passed as inputs instead of replacing them, which OnPush does not detect.
- Expecting OnPush to detect changes from services or events outside inputs without manual triggers.
- Not using
ChangeDetectorRef.markForCheck()when needed to manually trigger checks.
Always provide new object references to inputs to trigger OnPush change detection.
typescript
import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; @Component({ selector: 'app-bad-child', template: `<p>{{ items.length }}</p>`, changeDetection: ChangeDetectionStrategy.OnPush }) export class BadChildComponent { @Input() items: string[] = []; addItem(item: string) { // Wrong: mutating input array this.items.push(item); } } // Correct approach: // Replace the array with a new one to trigger change detection // this.items = [...this.items, newItem];
Quick Reference
- Use OnPush to optimize performance by reducing change detection cycles.
- Inputs must be immutable or replaced with new references to trigger updates.
- Use markForCheck() to manually trigger detection when needed.
- Events inside the component also trigger change detection automatically.
Key Takeaways
Set changeDetection to ChangeDetectionStrategy.OnPush in your component decorator to optimize checks.
OnPush triggers change detection only when input references change or events occur inside the component.
Avoid mutating input objects; always replace them with new references to trigger updates.
Use ChangeDetectorRef.markForCheck() to manually request change detection if needed.
OnPush improves performance by skipping unnecessary checks but requires careful data handling.