Thought leadership from the most innovative tech companies, all in one place.

Angular Change Detection Strategy — onPush and Default Strategy

Understand the onPush and Default Change Detection Strategies in Angular.

TechnoFunnel provides another article on Angular Change Detection Strategy. There are 2 change detection strategies in Angular (Default and onPush). We will look for the advantages and disadvantages of using these strategies.

Angular Change Detection Strategies (onPush and Default)Angular Change Detection Strategies (onPush and Default)

What is Change Detection in Angular?

Angular Change Detection is responsible for making the component dynamic. During Change Detection Cycle, Angular looks for all the bindings, re-executes all the expression, compares it with the previous values and if the change is detected, it propagates the change to the DOM Elements.

Change detection in Angular is executed when:

  1. There are updates to Angular State variable

  2. Events are invoked inside Angular Component

  3. @Input Values are updated for the Components

What is Change Detection Strategy in Angular ?

Angular Change Detection Strategy are the methods by which the updates to the component is tracked and component is triggered to Re-render. There are majorly 2 Change Detection Strategy in Angular. We can configure the Change Detection Strategy for the Component inside the Decorator.

  1. Default Strategy

  2. onPush Strategy

Default Change Detection Strategy

Default change detection strategy is applied to the component while it is created. If a component strategy is not configured, it is marked as default. In this strategy, the change detection cycle runs on each and every event that occur inside the Component.

  1. Click event of elements

  2. Receiving data via asynchronous call

  3. Triggering setTimeout and setInterval

Let's look for issues associated with this Default Change Detection Strategy:

Given above are 2 Components: ParentComponent and ChildComponent. The Parent Component contains a property “counter”, that can be updated every time when the user clicks the button. The Component is re-rendered every time the value of “counter” updates. This component also contains a Child Component. The Child Component is independent of “counter” data since we are not passing data to the ChildComponent using @Input.

@Component({
  selector: "app-root",
  template: `
    <div>
      <h1>Counter Value: {{ this.counter }}</h1>
      <input
        type="button"
        (click)="this.updateCounter()"
        value="Update Counter"
      />
      <child-component></child-component>
    </div>
  `,
})
export class ParentComponent {
  counter = 0;

  updateCounter() {
    this.counter += 1;
  }
}

Let’s look into the implementation of ChildComponent, the ChildComponent is a static component that do not have any impact of change of Parent Data. Even if the counter value of the Parent Component updates, the view of ChildComponent should remain unchanged. In the below Component, we are not providing any Strategy inside the @Component Decorator. By default, it is configured as “Default Change Detection Strategy

@Component({
  selector: "child-component",
  template: `
    <div>
      <h3>{{ this.executeFunction() }}</h3>
    </div>
  `,
})
export class ChildComponent {
  executeFunction() {
    console.log("App Rerendered");
    return "This is Child Component";
  }
}

In the Default Change Detection Strategy, every time when we update the counter in the ParentComponent, the ChildComponent life Cycle is also triggered to re-render, this Child Component is re-rendered even when the change of Counter has no impact on the view of Child Component. Child Component is Independent of Data of Parent Component.

In the above code, every time when the Child component Renders, it console logs the message “App Rerendered”. Every time when we see the message in the console window, it means that the Child Component is also getting re-rendered. You can look for the online editor link given below to test the behavior in case of Default Change Detection Strategy. default-change-detection-strategy - StackBlitz Starter project for Angular apps that exports to the Angular CLIstackblitz.com

This Default Strategy is less performant since there are extra render cycles involved for the child component even if there is no impact.

onPush Change Detection Strategy

In order to address the above-stated problem, we work with “onPushDetection Strategy. During this Change Detection Strategy, the ChildComponent is not always dirty checked, if the parent element is updating the values that are not passed as “@Input” properties to the Child Component, then the child Component should not be dirty checked.

Benefits of onPush Change Detection

  • No Unnecessary Dirty Check in the Child Components

  • Faster Component Re-rendering

@Component({
  selector: "child-component",
  template: `
    <div>
      <h2>{{ this.executeFunction() }}</h2>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ChildComponent {
  executeFunction() {
    console.log("App Rerendered");
    return "This is Child Component";
  }
}

In the above code, we have updated the Change Detection Strategy for the Child Component. Since the change detection strategy is updated to OnPush, the component will not refresh/re-render, if the parent component’s property updates. In the above code since we do not have any @Input property getting updated, the component will not re-render and this would be more performant.

Be Cautious about Object Mutation:

The objects that are received as @Input property should not be mutated. When @Input Objects are received from the parent Component, it is received as reference. If the original object is mutated from the parent element, the reference is not updated in the Child Component, so @Input Component is not receiving a new reference and will not be updated since the Objects in @Input property as still same (reference).

In this case, there is no mechanism which can notify the child component that one of the properties of the @Input has been updated. We should create a new object with updated properties so that the reference of @Input property updates and the Child component is notified about the Component Update, hence re-rendering the component. onpush-change-detection-strategy - StackBlitz Starter project for Angular apps that exports to the Angular CLIstackblitz.com

Refer to the above code for implementation of the OnPush strategy.




Continue Learning