Friday, 18 April 2025

Angular 19 | Chapter 7 | Tracking Angular Application State with Signals

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

 

3 comments:

  1. 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.

    The 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.

    ReplyDelete
  2. 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.

    ReplyDelete
  3. The 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