In Angular 18, signals, computed, and effects are reactive primitives designed to handle state and trigger updates in a precise and efficient way. Here’s an overview of these concepts and guidance on when to use them:
1. Signals
What are they? • Signals are containers for reactive state. They hold a value and notify consumers when the value changes. • They are functions that can: • Get the current value by calling the function (e.g., signal()). • Set a new value using .set(). • Update the value based on the current one using .update().
Example:
import { signal } from ‘@angular/core’;
const counter = signal(0);
counter.set(5); // Update the value to 5 console.log(counter()); // Access the value: 5 counter.update(value => value + 1); // Increment value: 6
When to use: • Use signals for local, standalone state management, like managing counters, toggles, or other simple values that change over time. • Ideal when you want fine-grained reactivity without affecting the entire component tree.
2. Computed
What are they? • Computed signals derive their value from other signals. They automatically recalculate whenever the underlying signals change. • Think of them as “read-only reactive values.”
Example:
import { signal, computed } from ‘@angular/core’;
const firstName = signal(‘John’); const lastName = signal(‘Doe’);
const fullName = computed(() => `${firstName()} ${lastName()}`); console.log(fullName()); // “John Doe”
firstName.set(‘Jane’); console.log(fullName()); // Automatically updates: “Jane Doe”
When to use: • Use computed signals when you need to derive or transform data from other signals. • Common for calculated values or formatting outputs based on state changes.
3. Effects
What are they? • Effects are side-effect mechanisms that execute whenever a signal or computed signal they depend on changes. • They’re useful for triggering actions like API calls, DOM updates, or logging when reactive state changes.
Example:
import { signal, effect } from ‘@angular/core’;
const count = signal(0);
effect(() => { console.log(`Count changed to: ${count()}`); });
count.set(1); // Logs: “Count changed to: 1”
When to use: • Use effects for performing side effects tied to reactive state changes. • Examples include: • Triggering HTTP requests. • Updating a non-reactive DOM element. • Debugging or logging.
How to Decide Which to Use
Use Case Preferred Concept Storing a piece of state Signal Calculating derived state Computed Performing side effects (e.g., API calls, logging) Effect
Best Practices 1. Minimize Effects: Use effects sparingly for true side effects only. Avoid embedding complex logic within effects—prefer signals and computed signals for managing data. 2. Avoid Nested Computed/Effects: Keep the dependency graph clear to maintain predictability and avoid performance bottlenecks. 3. Compose Signals and Computed: Combine these primitives for a clean, reactive data flow.
By choosing the right concept for your needs, you can create Angular applications that are more efficient, readable, and maintainable【8】【9】【10】.