3 min read
Angular Change Detection
September 24, 2020
At OnceHub, we are continuously looking for ways to improve performance and create a better user experience.
One way to do that is with the change detection strategy in Angular.
Ever since the Angular framework was created, Angular change detection has been a subject of great discussions and curiosity. This blog post will explain what Angular change detection is, how it works, and the different strategies Angular provides.
In Angular, we have a view (template) and a model (component). We need to keep both of them in sync so whenever we make a change in the component, it will get rendered by the template immediately. This syncing process is called change detection.
Angular handles this for us with its own change detection mechanism.
Angular change detection mechanism
Angular always keeps track of all the components and updates the view immediately. Upon application startup, a change detector is created for each UI component and arranged in a tree. In each change detection cycle, Angular uses a recursive approach with depth-first search algorithm to identify and re-render the updated component’s view. The Angular change detection cycle gets triggered by the DOM events, timers, observables, and so on.
Angular provides two change detection strategies:
Default change detection strategy
The name itself states that Angular uses this by default. In this strategy, Angular traverses each and every component in the component UI tree in a recursive approach and re-renders the view if the content is updated in the model.
Now let’s move to the OnPush strategy.
OnPush Change Detection Strategy
If you are developing a large application like OnceHub, where we support a large application consisting of many features, running the checks for the entire application again and again is not a good approach. Although Angular can perform change detection very quickly, we can still improve the performance with OnPush.
What if I told you that instead of checking the component in each and every cycle, we will check it only when it’s required? Yes, this is possible with onPush change detection strategy.
In Angular, if a component is using onPush change detection (component C in the image below), the component itself and its all children will be skipped in regular change detection cycle and will be checked only when:
- Component’s input changes,
- Observable with async pipe emits a value,
- We force it to run manually,
- HTML template emits events
When a component uses the onPush change detection strategy, only the above rules will cause the component or its child components to be updated. This cannot be overridden by a child component.
How will the template get updated in onPush?
Now let’s suppose component C or any of its children generates any of the above four cases, then the entire path from that component to the root will be marked for check and will be re-rendered in the next cycle.
Points to consider while using onPush
So from the above discussion, onPush looks great, but “with great power comes great responsibility”. When we are using onPush strategy, we need to consider the following points:
- Add change detection to a parent when all of its children are already using it.
To understand this, suppose that you have added OnPush to component A and refactored the code so that it will be checked only when this component triggers one of the above four rules. However, you didn’t refactor child component B. When a simple variable, which is used in template, changes in component B, it will not trigger any of the above case and angular will never get notified that it needs to re-render component B. And template of component B will still show the old value.
Therefore, if you want to use onPush in any component, it’s always better to change all the children first and only then add it to the parent.
- Remember that adding OnPush to one or more components will not improve the performance much, because angular change detection cycle is still checking all other components every time.
So if you want to use it, use it in almost every component.
Using the onPush strategy is an overall win situation because without it, Angular is running change detection on each component for no reason and wasting CPU cycles.
We have started using onPush change detection strategies in our project and applying it to more and more components every day. Hopefully soon, all our components will use it and we can see significant performance improvements.
Prakash Verma, Software Engineer
Prakash started his career as an Angular Developer in January 2017. From the very beginning, he was crazy about Angular and worked on various Angular versions, starting from Angular 2. He joined OnceHub as a software engineer in June 2019. At work, he is in love with good quality code and at home, he loves listening to music and reading/writing poetry.