DISCOVERY

March 12th, 2019

Angular: Default vs. OnPush Change Detection

Angular

React

TypeScript

DOM

In the last few months I've written articles about lifecyles in React and Angular. Certain lifecycles in React and Angular are triggered by their respective change detection mechanisms. In React the change detection mechanism is triggered whenever a components state changes or the properties passed from a parent component change. In Angular the change detection mechanism is triggered whenever a DOM event occurs or values used in the component template are mutated (along with async code returning, timeouts completing, etc.).

Angular also allows developers to change the change detection strategy on a per-component basis. This post explores the two change detection strategies - Default and OnPush.

By default, Angular uses the ChangeDetectionStrategy.Default change detection strategy. Default tracks alterations to Angular's two-way data binding system. One thing this strategy checks for is changes to variables in the component templates1. Variable alterations include both value and reference changes.

Another thing Default checks for is DOM events. At a low level Angular monkey patches functions in the DOM API such as addEventListener()2. This allows Angular to perform its own logic whenever the DOM is altered or interacted with.

Monkey Patch

Alterations to a function or other program components at runtime. The patch is only visible to the current programs execution context. Monkey patching occurs in dynamic programming languages.

Other things Default change detection checks for includes asynchronous callbacks and timeout completions3.

ChangeDetectionStrategy.OnPush change detection is used as an optimization technique. For DOM events OnPush works similarly to Default. The DOM API is monkey patched and change detection runs when a DOM event occurs.

Differences arise when handling variable changes in component templates. By using OnPush, we tell Angular that the component uses immutable objects in its template4. OnPush will only trigger change detection when a template variable reference changes. Change detection will not trigger when a template variable is mutated.

To help visualize the differences between Default and OnPush I created an Angular application with two nearly identical components. One uses OnPush and the other uses Default change detection. I log every time a change detection cycle occurs to make things clearer.

The major takeaway from this project is that OnPush results in fewer change detection cycles. However, be careful and make sure all objects are immutable. If variables mutate, unexpected UI changes (or lack thereof) are likely to occur.

I find it very interesting how Angular handles its change detection mechanism. I look forward to learn more about the topic in the future. You can check out the code for my change detection project on GitHub.

[1] "Angular Change Detection - How Does It Really Work?", https://bit.ly/2Uw6HuV

[2] "Overriding browser default mechanisms", https://bit.ly/2NW0nub

[3] "Angular 2, 4 — Visualizing Change Detection (Default vs OnPush)", https://bit.ly/2HeXh3E

[4] "A Comprehensive Guide to Angular onPush Change Detection Strategy", https://bit.ly/2NYIevI