On the road to Fine-Grained Change Detection
Tags: angular
Published: 2023-11-01 14:46:54

A pull request was recently merged and will be available in the upcoming major version v17. This pull request represents the first step towards fine-grained reactivity and signal-based components.

If you want to read more, click the pull request below:

{% embed https://github.com/angular/angular/pull/52302 %}

The goal of this change is to refresh **ONLY** the component where the change occurred, but there are a couple of requirements:

- All your components need to use **OnPush**.
- The change has to be triggered by a **Signal**.

Let's take a step back and explain why we need OnPush and Signals to benefit from local change detection.

## How Change Detection Works 

Angular employs **Zone.js** to detect changes and trigger a new render. Since Zone.js doesn't track where a change occurred, Angular performs a top-to-bottom rerender. This means that Angular refreshes the RootComponent down to all ChildComponents. This operation is fast but costly since Angular rerenders all components even if only a small change occurred.

Meanwhile, **ChangeDetectionStrategy.OnPush** was introduced to optimize the change detection cycle. When a component is marked for check, all its ancestors are also marked for check. Then Angular triggers a top-down cycle and only refreshes the marked components.

In v16, Angular introduced Signals, a new reactive API. This API allows Angular to precisely determine where a change is occurring. Angular can now identify which components need to be refreshed. A Signal marks the component as dirty but not its ancestors. When Angular performs its top-down change detection cycle, only that specific component will be refreshed.

## Notes:
- Angular still needs to perform a top-down change detection to maintain backward compatibility with previous versions and with components not using Signals, relying on Zone.js instead.
- Currently, Angular cannot achieve more granularity than per-component because it might disrupt how non-signal components are refreshed. In the future, the goal is to be more granular, but it will never be as granular as the binding. Refer to the [RFC](https://github.com/angular/angular/discussions/49684) for more details.

## Conclusion:
Now you should understand why this change will benefit applications that leverage the use of Signals and OnPush. 

1. Signals allow Angular to precisely pinpoint where the change occurred and mark only the affected component as dirty. 
2. OnPush is necessary because Angular still requires a top-down change detection, and it only refreshes OnPush components when marked for check. All Default components will still be rerefreshed.

{% embed https://twitter.com/laforge_toma/status/1721422293723754573 %}

---

Update your application to v17 and start using Signals, as this is just the beginning of how Signals can enhance your Angular application.

---

You can find me on [Twitter](https://twitter.com/laforge_toma) or [Github](https://github.com/tomalaforge).Don't hesitate to reach out to me if you have any questions.

---

_Thanks to [Enea](https://twitter.com/Enea_Jahollari) for reviewing it._