🅰️ Angular Q82 / 125

What are Angular signals?

AI-Powered Answer ✓ Answered

Angular Signals are a new reactivity primitive introduced in Angular to manage state changes in a more explicit, granular, and performant way. They represent a value that can change over time, notifying interested consumers when an update occurs. This modern approach aims to simplify state management and improve change detection mechanisms within Angular applications.

What are Signals?

Signals are zero-argument functions that return their current value. When a signal's value changes, it automatically notifies any computations or effects that depend on it. This push-based change detection system allows Angular to update only the specific parts of the UI that are affected by a change, rather than re-checking the entire component tree.

  • Granular Reactivity: Signals track dependencies automatically, enabling highly optimized updates.
  • Value-Based: They encapsulate a single value, making state changes explicit and predictable.
  • Push-Based: Consumers are notified when a signal's value changes, leading to efficient updates.

Core Signal Concepts

signal()

The signal() function creates a writable signal. You can update its value using the .set() method or the .update() method for more complex transformations based on the current value.

typescript
import { signal } from '@angular/core';

const count = signal(0);
console.log(count()); // Output: 0

count.set(5);
console.log(count()); // Output: 5

count.update(currentCount => currentCount + 1);
console.log(count()); // Output: 6

computed()

computed() creates a read-only signal that derives its value from one or more other signals. It automatically re-evaluates only when its dependencies change, and its value is cached until then, making it efficient for derived state.

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

const firstName = signal('John');
const lastName = signal('Doe');

const fullName = computed(() => `${firstName()} ${lastName()}`);

console.log(fullName()); // Output: John Doe

firstName.set('Jane');
console.log(fullName()); // Output: Jane Doe

effect()

effect() registers a side effect that will run whenever one of its signal dependencies changes. Effects are useful for synchronizing signal state with the DOM, logging, or other non-signal-based APIs. They are typically used for rendering or debugging and should generally be avoided for managing core application state.

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

const message = signal('Hello');

effect(() => {
  console.log(`Current message: ${message()}`);
});

message.set('World'); // Output: Current message: World (due to effect)

Benefits of Using Signals

  • Improved Performance: More granular change detection reduces the amount of work Angular needs to do on each update.
  • Simplified State Management: State changes become more explicit and easier to reason about.
  • Better Developer Experience: Provides a clear and consistent pattern for reactivity, reducing reliance on NgZone and Zone.js for many use cases.
  • Future-Proofing: Aligns Angular with modern reactivity patterns seen in other frameworks, paving the way for further optimizations.

Integration with Components

Signals can be seamlessly integrated into Angular components. You can declare signals as component properties, use them in templates, and update them based on user interactions or data fetched from services. Signals naturally fit into component lifecycle and data flow, providing a powerful tool for reactive UI updates without needing to manually subscribe/unsubscribe from Observables for simple state.

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

@Component({
  selector: 'app-counter',
  template: `
    <p>Count: {{ count() }}</p>
    <button (click)="increment()">Increment</button>
  `,
  standalone: true
})
export class CounterComponent {
  count = signal(0);

  increment() {
    this.count.update(currentCount => currentCount + 1);
  }
}