Change Detection & Zone.js
Understand how Angular decides when to re-check the DOM, from classic Zone.js-based detection to modern signal-based precision.
What Is Change Detection?
Change detection is the process Angular uses to check whether any component's data has changed, and if so, update the DOM to match. Understanding roughly how it works helps explain both classic Angular's performance characteristics and why Signals were introduced.
How Zone.js Triggers It
By default, Angular includes Zone.js, a library that patches common async browser APIs (setTimeout, Promise callbacks, DOM events) so Angular is notified whenever one of them completes. After any such event, Angular re-checks the entire component tree from the root, comparing each binding's current value to its last-known value.
ChangeDetectionStrategy.OnPush
Setting a component's change detection strategy to OnPush tells Angular to skip re-checking it unless one of its @Input() references actually changed (or an event originated from within it) — a common, effective optimization for components deep in a large tree.
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
@Component({ selector: 'app-product-card', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<h3>{{ product.name }}</h3>`,})export class ProductCardComponent { @Input() product!: { name: string };}With OnPush, mutating an object's property in place (product.name = 'New') won't trigger a re-check — you need to pass a genuinely new object reference for Angular to notice the change.
How Signals Change the Picture
Signals sidestep this whole broad-recheck model. Because a signal knows exactly which template bindings read it, Angular can update just those specific bindings directly, without walking the rest of the component tree at all — a fundamentally more precise (and, for large apps, more scalable) approach.
| Zone.js (Classic) | Signals | |
|---|---|---|
| Trigger | Any patched async API completing | A specific signal being written to |
| Scope of recheck | The whole component tree (unless OnPush) | Only bindings that actually read that signal |
| Requires Zone.js? | Yes | Angular can run zoneless with signals (an evolving capability) |
Common Beginner Mistakes
Angular compares references, not deep equality — always create a new object/array when the data genuinely changed, so OnPush components notice.
They dramatically reduce how often you need to reason about it, but understanding the underlying model still helps when debugging an unexpected stale (or overly frequent) update.
FAQs
It's a good default habit for presentational components fed entirely by inputs, but always update input data immutably if you do — otherwise UI can silently fail to refresh.
Angular has been moving toward optional, signal-driven "zoneless" change detection — check current Angular release notes for the latest state of this transition.
Summary
Classic Angular re-checks broadly via Zone.js, OnPush narrows that scope for immutable-input components, and Signals enable the most precise updates of all. With standalone components and Signals covered, the next section moves into services and dependency injection.