Angular has always relied on Zone.js to detect when data changes and the UI needs to update.
However, this approach is often heavy and can lead to performance issues in massive applications.
To solve this, Angular introduced Signals, providing highly optimized, fine-grained reactivity!
A Signal is a wrapper around a value that automatically notifies Angular whenever that value changes.
When a Signal updates, Angular knows exactly which specific HTML elements need to re-render.
This completely eliminates the need for Angular to scan the entire component tree looking for changes.
To create a Signal, you import the signal function from @angular/core.
You pass your initial value into the function.
To read the value of a Signal, you must call it like a function: mySignal().
import { Component, signal } from '@angular/core';
@Component({
template: '<p>Count: {{ count() }}</p>'
})
export class CounterComponent {
// Creates a Signal initialized to 0
count = signal(0);
}
Because Signals are protected wrappers, you cannot reassign them directly using =.
Instead, you use the .set() method to completely overwrite the value.
Or, you use the .update() method to compute a new value based on the previous value.
export class CounterComponent {
count = signal(0);
increment() {
// Updates the signal based on its previous value
this.count.update(currentValue => currentValue + 1);
}
reset() {
// Completely overwrites the signal value to 0
this.count.set(0);
}
}
If you need a value that depends on another Signal, you use computed().
Computed Signals are automatically recalculated only when their dependent Signals change, making them highly efficient!
import { signal, computed } from '@angular/core';
count = signal(2);
// Automatically stays in sync. If count is 2, doubleCount is 4!
doubleCount = computed(() => this.count() * 2);
How do you extract and read the value inside an Angular Signal variable named 'userName'?