DEV Community

Cover image for Angular Signals🚦: New Change detection strategy
Madhu Sudhanan P
Madhu Sudhanan P

Posted on • Originally published at maddydeep28.Medium

Angular Signals🚦: New Change detection strategy

The hype around Angular signals is real. If you are an Angular user, I hope, you already know the answer. Signal is going to be the new change detection strategy.

There are many articles available online now that are deep-diving into the Signals concepts. I suppose it’s also worth sharing my understanding of the concept.

Change detection: What is the current state and What will be the future?

Angular is currently relying on the Zone js for the change detection. Zone Js will monkey patch various built-in APIs to notify the change in the application. If a new Web API is introduced in JavaScript then Zone Js has to be updated by monkey patching the new API so relying on Zone Js is not a future-proof solution.

Another major setback with this approach is that there is no information about the component that is responsible for the change and what changed in the model. Due to this, to reflect the model changes in the DOM, the application has to traverse from top to down to identify and apply the changes. The component traversal can be customized by the OnPush change detection strategy though.

Also, many users like to have zoneless applications and various experiments can be seen online.

To tackle these problems, Angular started to revisit its current change detection strategy which results in the signals concepts that provide fine-grained control over the component change detection.

Signals bring the below advantages to Angular.

  • Updates only the components that interest the model value change by providing the information on the model change.
  • Removes top-down component traversal. It only updates the component that uses the signal.
  • No dirty monkey patching of global methods/APIs.

Building Blocks of Angular Signal

The below items are the major building blocks of the Angular signal.

  • Signal
  • Computed signal
  • Effect

What is signal?

Signal is a lightweight wrapper around a value that notifies the value changes to the interested consumers. It comes with several methods that allow us to set, update, and mutate its value.

You can initialize the signal value by using the signal method.

export class AppComponent {
  count = signal(0);
}
Enter fullscreen mode Exit fullscreen mode

set method can be used to change the initialization value of the signal. The signal value is changed to a new value in the resetView method.

export class AppComponent {

  count = signal(0);

  resetView() {
    this.count.set(0);
  }
}
Enter fullscreen mode Exit fullscreen mode

update method will help you to change the value based on the previous value.

export class AppComponent {
  count = signal(0);

  addView() {
    this.count.update(val => val + 1);
  }

  resetView() {
    this.count.set(0);
  }
}`
Enter fullscreen mode Exit fullscreen mode

mutate method will allow you to mutate the signal in its place and notify its dependencies.

Computed signal properties

Another interesting part of the signal is the computed signal properties. The computed signal is a long-requested feature in Angular and, introducing it as a part of the signal has major advantages for both developer experience and performance of the application.

The computed function can be used to create a computed signal property.

export class AppComponent {

  count = signal(0);

  revenue = computed(() => this.count() * 0.5);

  addView() {
    this.count.update(val => val + 1);
  }

  resetView() {
    this.count.set(0);
  }
}
Enter fullscreen mode Exit fullscreen mode

The computed signal property has the following behavior.

  • Computed properties are lazily initialized. The computation will not happen until the value is accessed.
  • It shuffles the dependency graph dynamically based on the dependency signal change. Angular is being cautious in the dynamic dependency graph since the frequent setting of the dependency graph will come at a cost.

Effect

The effect function allows you to listen to the signal changes and act based on them. The effects can be used to handle some use cases like,

  • Custom updating DOM after one or more signals are changed.
  • Trigger network requests.

The effect will auto-subscribe itself based on the signals used in its context. For example, the below list of effect methods used in the constructor will be called in various signal changes.

export class AppComponent {
  count = signal(0);
  user = signal(0);

  constructor() {
      effect(() => {
        console.log('Empty effect method');
      });

      effect(() => {
        console.log('User effect invoked ' + this.user());
      });

      effect(() => {
        console.log('User and View effect invoked ' + this.user() + ' ' + this.count());
      });

      effect(() => {
        console.log('Count effect invoked ' + untracked(this.count));
      });
  }

  addView() {
    this.count.update(val => val + 1);
  }

  userChange() {
    this.user.update(val => val + 1);
  }

  resetView() {
    this.count.set(0);
  }
}
Enter fullscreen mode Exit fullscreen mode

This effect method will be called only once since no signal property is used in its context.

effect(() => {
  console.log('Empty effect method');
});
Enter fullscreen mode Exit fullscreen mode

The below effect will be called whenever the user signal is changed.

effect(() => {
  console.log('User effect invoked ' + this.user());
});
Enter fullscreen mode Exit fullscreen mode

This callback will be invoked when either the user or count signal is changed.

effect(() => {
  console.log('User and View effect invoked ' 
               + this.user() + ' ' + this.count());
});
Enter fullscreen mode Exit fullscreen mode

This effect method will be called when the very first time the count signal is set then it will become inert since the count is wrapped in the untracked method. This method will help you execute the signals inside a non-reactive context.

effect(() => {
  console.log('Count effect invoked ' + untracked(this.count));
});
Enter fullscreen mode Exit fullscreen mode

Using signals in the templates

The angular team chooses the getter function approach to use signals inside the templates.

<div>
  <span>Unique users: </span>
  <span>{{users()}}</span>
</div>
Enter fullscreen mode Exit fullscreen mode

The team sees some clear advantages in using the getter function approach like it implies that it is meant for read operation and maintains consistency between the component and template files.

Over the years Angular developers learned not to use functions inside the template since it would have a considerable performance impact if the method did some heavy work. But it's not the case with signals since they are built to do computations in a minimal way.

Upcoming works — signals

Well, signals in Angular is a bit large topic and I just covered a very small part of it. The angular team is still working on introducing several changes in the input/output, control flow and defer loading to improve the developer experience and ability to add Zone-less(Fully signal)-based applications in the future.

If you find this article helpful, please follow me here and on twitter for more content like this.

Happy coding…

Top comments (3)

Collapse
 
akashkava profile image
Akash Kava

@madhust Have a look at Web Atoms, all the great features are already there which will come to Angular.

Collapse
 
szagi3891 profile image
Grzegorz Szeliga

Signals may be an amazing thing that happened to angular

Collapse
 
madhust profile image
Madhu Sudhanan P

Yes. Its a great addition to the framework and resent works by the Angular core team is really amazing, it improves my confidence with the framework.