Tracking Angular web application state with Signals is part of Angular's modern reactive approach — it's super clean, fast, and intuitive. Angular Signals were introduced as a way to make reactivity simpler and more predictable than RxJS alone in certain cases.
๐ง What Are Signals in Angular?
Signals are a way to track
reactive values and automatically update the UI or other logic when
those values change.
They’re similar to BehaviorSubject
or computed properties in other frameworks, but:
- They’re
built into Angular.
- No
need to manually subscribe() and unsubscribe().
- Way
less boilerplate than RxJS for basic state tracking.
๐งฉ Basic Signal Concepts
- signal()
– creates a reactive value
- computed()
– creates a derived value based on other signals
- effect()
– runs side effects when signal values change
๐ Example: Managing State with Signals
Let’s say we want to
manage a task list in a service:
import { Injectable,
signal, computed, effect } from '@angular/core';
@Injectable({
providedIn: 'root' })
export class TaskService {
private tasks =
signal<string[]>([]); // ✅ Reactive signal
// Public read-only
signal
readonly tasks$ = computed(() =>
this.tasks());
// Add a task
addTask(task: string) {
this.tasks.update(current =>
[...current, task]);
}
// Remove a task
removeTask(index: number) {
this.tasks.update(current =>
current.filter((_, i) => i !== index));
}
}
Now in a component:
@Component({
selector: 'app-task-list',
standalone: true,
template: `
<ul>
<li *ngFor="let task of
taskService.tasks$()">
{{ task }}
</li>
</ul>
`,
})
export class TaskListComponent {
constructor(public taskService:
TaskService) {}
}
✅
You get reactivity with zero subscriptions
✅
Any changes to tasks will automatically reflect in the template
✅
No need for async pipe, OnPush, or ChangeDetectorRef
๐ Signal Lifecycle Helpers
effect()
Trigger code when a
signal changes (side effects):
effect(() => {
console.log("Tasks updated:",
this.tasks());
});
computed()
Create a signal that derives
from others:
readonly taskCount =
computed(() => this.tasks().length);
๐ก Why Use Signals for State?
|
Benefits |
Compared
to |
|
Zero
manual subscriptions |
RxJS |
|
Automatic
change detection |
ChangeDetectorRef,
OnPush |
|
Cleaner
syntax |
BehaviorSubject
& .next() |
|
Faster
and more predictable |
Especially
in component templates |
๐งช When to Use Signals vs RxJS?
|
Use
Signals When... |
Use
RxJS When... |
|
Local
or simple global state |
Complex
async flows (HTTP, websockets) |
|
You
want template reactivity with ease |
You
need stream operators (switchMap, etc.) |
|
Need
minimal boilerplate |
Need
more stream control |
๐ง Summary
|
Concept |
Description |
|
signal() |
Creates
a reactive variable |
|
computed() |
Creates
a derived value based on signals |
|
effect() |
Reacts
to signal changes (side effects) |
|
update() |
Updates
signal values cleanly |
Angular Signals offer a straightforward approach to tracking application state by making reactive values update automatically when their underlying state changes. The article clearly introduces signal(), computed(), and effect() and demonstrates how they fit together in an Angular service and component.
ReplyDeleteThe task-list example shows how a service can maintain reactive state without manually managing subscriptions, while the template reads the current value directly. For developers working with Angular Course, this provides a practical example of how Signals can simplify everyday component state management.
The distinction between Signals and RxJS is also useful because the article presents them as suitable for different situations. Developers learning TypeScript Course can relate the example to cleaner state-oriented code, while recognizing that RxJS remains useful for complex asynchronous flows and stream operators.
ReplyDeleteThe discussion of computed() and effect() further demonstrates how derived values and side effects can be handled within the Signals model. This makes the concepts relevant when developing Angular Projects that require reactive UI updates without unnecessary subscription and change-detection boilerplate.
ReplyDelete