3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Lesson 8

Change Detection: OnPush vs Default

Why OnPush change detection matters

STANDARD

Change Detection: OnPush vs Default

To get right to the point: Angular needs to keep track of when things in your application change. Let’s say we have a class member in the class for my component:

@Component({
  selector: 'app-home',
  template: `
    <p>{{ name }}</p>
    <button (click)="changeName()">Change name</button>
  `,
})
export class HomeComponent {
  name = 'Josh';

  changeName() {
    this.name = 'Kathy';
  }
}

The value for name is initially Josh and we are displaying that in the template. But, we have a button that triggers the changeName method when clicked which will change this value to Kathy. I encourage you to run this example for yourself, because we are going to play with this a bit.

If you click the button, you might be unsurprised to see that the value displayed in the template changes. This is what we would want to happen, but the underlying mechanisms for Angular to achieve this seemingly simple task aren’t so simple.

We could cause a change to the template in a different way - what about a setTimeout that triggers the change after 2 seconds?

@Component({
  selector: 'app-home',
  template: ` <p>{{ name }}</p> `,
})
export class HomeComponent implements OnInit {
  name = 'Josh';

  ngOnInit() {
    setTimeout(() => (this.name = 'Kathy'), 2000);
  }
}

NOTE: We are using one of Angular’s lifecycle hooks here to run some code when the component is initialised. There are other Angular lifecycle hooks like OnDestroy and AfterViewInit as well.

Or, maybe we have a setInterval changing the value every second:

@Component({
  selector: 'app-home',
  template: ` <p>{{ value }}</p> `,
})
export class HomeComponent implements OnInit {
  value = 1;

  ngOnInit() {
    setInterval(() => this.value++, 1000);
  }
}

If you run these examples, you will see that in every case the value is updated correctly. Angular detects when these changes occur and updates the template.

How does Angular detect changes?

We aren’t going to get into the precise underlying mechanisms that allow Angular to detect and respond to changes. This can become useful for performance optimisation, but it isn’t something we need to get into right now.

Our main goal in this lesson will be to understand the difference between the Default change detection strategy, and the OnPush change detection strategy. To do that, we need to understand a little bit about how the default change detection strategy works.

The key idea behind how Angular is able to achieve this is that it uses something called Zone.js to detect when any code runs that has the potential to cause a change. The scenarios that might cause a change to your applications state include:

  1. Component initialisation
  2. Events being triggered (like our button click from before)
  3. Handling the response of an HTTP request
  4. MacroTasks such as setTimeout() and setInterval()
  5. MicroTasks such as handling Promises

But there are also some other scenarios that could cause a change. Since Angular knows when something has happened that might cause a change, it can check your application to see if anything has changed and render the update if necessary.

With the Default change detection strategy, Angular will check every component in the component tree. If one of these scenarios that might cause a change occurs, then Angular will check all of these components to see if the data/model they depend upon has changed. In our examples, we were only changing the HomeComponent so the HomeComponent is the only one that needs to be updated, but Angular still needs to check every single component regardless.

This might sound bad, and it’s certainly not optimal, but using the Default strategy is generally fine in terms of performance. Angular can perform these checks quite quickly. Using OnPush change detection instead will still improve performance, but as we will discuss later, it isn’t the main reason we should use it (or at least I don’t think so).

Using OnPush Change Detection

Now let’s see how the OnPush change detection strategy differs from the default. We will revisit all of our examples from before, but this time we will update the component to use OnPush change detection (go ahead and try all of these):

import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
  selector: 'app-home',
  template: `
    <p>{{ name }}</p>
    <button (click)="changeName()">Change name</button>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HomeComponent {
  name = 'Josh';

  changeName() {
    this.name = 'Kathy';
  }
}
STANDARD
Key

Thanks for checking out the preview of this lesson!

You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).