Angular Signals — The Future of Reactivity in Angular

What Are Signals?
A Signal is a reactive value that:
Holds state
Notifies Angular when it changes
Automatically updates the UI
Think of it as a reactive variable with built-in change tracking
Why Angular Introduced Signals
Traditional Angular reactivity:
Relies on Zone.js
Uses RxJS streams
Can trigger unnecessary change detection cycles
Signals solve this by:
Enabling fine-grained reactivity
Reducing dependency on Zone.js
Making code simpler and more predictable
Core Concepts of Signals
1. Writable Signals
import { signal } from '@angular/core';
const count = signal(0);
// Read
console.log(count());
// Write
count.set(10);
// Update
count.update(value => value + 1);
2. Computed Signals
Derived state based on other signals.
import { computed } from '@angular/core';
const count = signal(5);
const doubleCount = computed(() => count() * 2);
console.log(doubleCount()); // 10
Automatically recalculates when dependencies change.
3. Effects
Run side effects when signals change.
import { effect } from '@angular/core';
effect(() => {
console.log('Count changed:', count());
});
Useful for logging, API calls, or syncing state.
Signals in Angular Components
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-counter',
template: `
<h2>{{ count() }}</h2>
<button (click)="increment()">+</button>
`
})
export class CounterComponent {
count = signal(0);
increment() {
this.count.update(v => v + 1);
}
}
Angular automatically re-renders when count changes — no manual detection needed.
Signals vs RxJS
| Feature | Signals | RxJS |
|---|---|---|
| Complexity | Simple | Complex |
| Learning curve | Low | High |
| Async streams | Limited | Powerful |
| UI state | Best | Overkill |
| Operators | No | Yes |
Rule of thumb:
Use Signals for local/UI state
Use RxJS for async streams & APIs
Interoperability with RxJS
Angular provides utilities to convert between Signals and Observables.
Observable → Signal
import { toSignal } from '@angular/core/rxjs-interop';
const dataSignal = toSignal(this.http.get('/api/data'));
Signal → Observable
import { toObservable } from '@angular/core/rxjs-interop';
const count$ = toObservable(count);
Advanced Features
1. Signal-based Inputs
@Input() count = signal(0);
2. Signal-based Stores (Lightweight State Management)
@Injectable({ providedIn: 'root' })
export class CounterStore {
count = signal(0);
increment() {
this.count.update(v => v + 1);
}
}
3. Computed Chains
const price = signal(100);
const tax = signal(10);
const total = computed(() => price() + tax());
Common Mistakes
Forgetting to call signal as function →
count()notcountUsing signals for heavy async logic
Replacing RxJS completely (not recommended)
Performance Benefits
Signals enable:
Fine-grained DOM updates
Reduced change detection cycles
Better scalability
This is a big step toward zone-less Angular
When Should You Use Signals?
Use Signals when:
Managing component state
Handling UI interactions
Creating derived state
Avoid Signals when:
Handling complex async flows
Working with streams (WebSockets, polling, etc.)
Future of Angular with Signals
Signals are not just a feature — they are the foundation of Angular’s future:
Zone-less applications
Better performance
Cleaner architecture
Final Thoughts
Angular Signals simplify reactivity while improving performance.
If you’re still using RxJS for everything, it’s time to rethink your approach.
Start small:
Replace local state with Signals
Use computed values instead of manual logic
Gradually adopt in your projects
What Do You Think?
Have you started using Signals in your Angular apps?
Let’s discuss.

