Reactivity in Angular is the process by which the framework determines that the application state has changed and, if necessary, refreshes the view or the DOM. If you’ve read the article Change detection strategy, the magic of Angular, you’ll know that Angular bases this detection on a component tree and mechanisms such as NgZone or ChangeDetectionStrategy to control when and how the UI is updated.

Today we’ll go one step further: we’ll see how Angular Signals, the new reactivity API in Angular introduced experimentally in Angular 16, makes it possible to improve UI efficiency, update only what is necessary, and simplify state management in Angular components, optimizing the performance of your applications.

The problem with classic change detection in Angular

In the traditional approach:

For example, in the previous article we created a clock that updates every second and a table of users. The clock update triggered a full Angular change detection cycle, recalculating random values in each row, even though the data had not changed.

Angular Signals: how they improve reactivity

With Angular Signals:

This makes Signals a key tool for improving performance in Angular, especially in large applications with lists and complex components.

Signals, effects, and derived values

To better understand it, let’s see how Signals work in Angular.

Create a signal

import { signal } from '@angular/core';

const counter = signal(0);

Effects (effect)

Effects are functions that run automatically when the signals they use change.

import { signal, effect } from '@angular/core';
const counter = signal(0);
effect(() => {
  console.log(`The counter value is ${counter()}`);
});
counter.set(1); // The effect runs and prints “The counter value is 1”

Computed values

You can compute a value from one or more signals without having to rewrite additional logic.

import { computed } from '@angular/core';

const double = computed(() => counter() * 2);

Advanced features of Angular Signals

In addition to what we have seen, Angular Signals includes several important features, according to the official documentation:

Computed is lazy and memoized

const counter = signal(0);
const double = computed(() => {
  console.log('Recalculando...');
  return counter() * 2;
});

Dynamic dependency tracking

Angular only tracks signals that are actually read within a computed or effect.

const show = signal(false);
const counter = signal(0);

const conditional = computed(() => show() ? counter() : 0);

Signals in templates

{{ counter() }}

untracked(): avoid reactive dependencies

Allows you to read a signal without registering it as a dependency within an effect or computed.

effect(() => {
  console.log(`User set to ${currentUser()} and the counter is ${untracked(counter)}`);
});

Live practical example: clock and user table with Angular Signals

Real case Angular Signals

Instead of showing all the code here, we’ve prepared an interactive example on StackBlitz so you can see Angular Signals working in real time.

In this example you will observe:

Try the live example on StackBlitz.

Visual comparison

Before (Default CD) Now (Signals)
Full change detection cycle every second Only what depends on a signal is updated
randomId was recalculated unnecessarily randomId remains stable
OnPush required for optimization No need for OnPush or ChangeDetectorRef
Performance affected with many rows Performance remains stable even when the clock updates

Conclusion

Angular Signals represents the evolution of the change detection model explained in our previous article.

Previously, any asynchronous event could trigger a full change detection cycle. Now, Angular updates only the bindings that depend on the signals that change, avoiding unnecessary computations and improving efficiency.

With Signals and derived values (computed), we can build faster, more predictable, and easier-to-maintain applications, especially as the component tree grows.

Tell us what you think.

Comments are moderated and will only be visible if they add to the discussion in a constructive way. If you disagree with a point, please, be polite.

Subscribe