Angular 20

Angular 20 State Management Tutorial – RxJS, NgRx & Angular Signals Explained

Chapter 12: State Management in Angular 20 (Standalone Components)

Managing state effectively is key for scalable Angular applications. In Angular 20, state management can be handled elegantly with services using RxJS, and enhanced with libraries like NgRx or Angular Signals. This chapter explores core state management techniques suitable for standalone component architecture.

1. Service-Based State Management

The simplest approach to manage state is to create a service that holds and manages shared data. Components inject the service and subscribe to changes.


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

@Injectable({
  providedIn: 'root',
})
export class CounterService {
  private count = 0;

  getCount() {
    return this.count;
  }

  increment() {
    this.count++;
  }

  decrement() {
    this.count--;
  }
}
  

However, this method doesn’t notify components of changes automatically, so it’s better to use reactive streams.

2. Using RxJS Subjects for Reactive State

Subject allows components to subscribe and react to state changes.


import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class CounterService {
  private count = 0;
  private countSubject = new Subject();

  count$ = this.countSubject.asObservable();

  increment() {
    this.count++;
    this.countSubject.next(this.count);
  }

  decrement() {
    this.count--;
    this.countSubject.next(this.count);
  }
}
  

Components can subscribe to count$ to receive live updates.

3. BehaviorSubject: Storing Current State

BehaviorSubject holds the current state value and emits it immediately on subscription.


import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class CounterService {
  private countSubject = new BehaviorSubject(0);

  count$ = this.countSubject.asObservable();

  increment() {
    this.countSubject.next(this.countSubject.value + 1);
  }

  decrement() {
    this.countSubject.next(this.countSubject.value - 1);
  }
}
  

Usage in Component


import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CounterService } from './counter.service';

@Component({
  standalone: true,
  imports: [CommonModule],
  selector: 'app-counter',
  template: `

Counter: {{ count }}

` }) export class CounterComponent { count = 0; constructor(private counterService: CounterService) { this.counterService.count$.subscribe(value => this.count = value); } increment() { this.counterService.increment(); } decrement() { this.counterService.decrement(); } }

4. Introduction to NgRx

NgRx is a powerful Redux-inspired state management library for Angular. It uses a unidirectional data flow and stores application state in a single immutable store.

Core concepts:

  • Store: Single source of truth for app state.
  • Actions: Events that describe state changes.
  • Reducers: Pure functions to handle actions and update state.
  • Effects: Handle side effects like API calls.

NgRx requires some setup but excels in large, complex apps where explicit state control is needed.

5. Angular Signals (Experimental)

Angular Signals provide a reactive primitive for state management with better performance and simpler APIs. Signals represent reactive values that components automatically track and update when changed.

Example usage:


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

@Component({
  standalone: true,
  selector: 'app-signal-counter',
  template: `

Signal Counter: {{ count() }}

` }) export class SignalCounterComponent { count = signal(0); increment() { this.count.set(this.count() + 1); } decrement() { this.count.set(this.count() – 1); } }

6. Summary

  • Service-based state is simple but limited without reactivity.
  • RxJS Subjects and BehaviorSubjects enable reactive and shared state management.
  • NgRx offers scalable state management with a unidirectional data flow.
  • Angular Signals provide a promising new reactive primitive for efficient state handling.

Next Chapter Preview

Next up, Chapter 13 covers Angular’s Lifecycle Hooks—how and when to use them for optimized component performance.

Leave a Reply

Your email address will not be published. Required fields are marked *