Reactivity has always been at the heart of modern frontend frameworks. In Angular, developers have relied on RxJS and change detection strategies to manage state and UI updates. However, with the introduction of Angular Signals (introduced in Angular v16 and improved in Angular v17+), state management and reactivity have become simpler, predictable, and more efficient.
In this blog, we’ll cover:
What are Angular Signals?
Types of Signals in Angular
Code examples with Signals
Best practices for using Signals
Why you should start adopting Signals today
🔹 What are Angular Signals?
A signal is a wrapper around a value that notifies consumers when that value changes. Unlike RxJS Observables, which are asynchronous streams, Signals are synchronous and track dependencies automatically.
This makes them:
✅ Easier to learn than RxJS
✅ More predictable with explicit reactivity
✅ Better performance with fine-grained change detection
In short: Signals tell Angular what changed, so Angular updates only what’s necessary.
🔹 Different Types of Signals in Angular
Angular provides three main types of Signals:
- Writable Signals
Writable signals are the most common type. They store a value and allow updates.
import { signal } from '@angular/core';
export class CounterComponent {
// Create a writable signal with default value
count = signal(0);
increment() {
this.count.set(this.count() + 1); // update value
}
decrement() {
this.count.update(value => value - 1); // functional update
}
}
📌 Usage in template:
<p>Current Count: {{ count() }}</p>
<button (click)="increment()">+</button>
<button (click)="decrement()">-</button>
- Computed Signals
Computed signals derive their value from other signals. They automatically recalculate when dependencies change.
import { signal, computed } from '@angular/core';
export class CartComponent {
price = signal(100);
quantity = signal(2);
// computed signal
total = computed(() => this.price() * this.quantity());
}
📌 Usage in template:
<p>Price: {{ price() }}</p>
<p>Quantity: {{ quantity() }}</p>
<p>Total: {{ total() }}</p>
When price or quantity updates, total is recalculated automatically.
- Effect Signals
Effects let you run side effects when a signal changes (e.g., logging, API calls, localStorage updates).
import { signal, effect } from '@angular/core';
export class LoggerComponent {
username = signal('Anshul');
constructor() {
effect(() => {
console.log(`User changed to: ${this.username()}`);
});
}
changeUser() {
this.username.set('Rohit');
}
}
Whenever username updates, the effect runs.
🔹 Best Practices for Using Signals
Here are some pro tips to make the most of Angular Signals:
Prefer computed over duplicate logic
Instead of recalculating values in multiple places, use computed.
Example: Calculating totals, formatted strings, or derived states.
Use update() for immutability
Use update() instead of set() when working with objects or arrays.
todos = signal<string[]>([]);
addTodo(newTask: string) {
this.todos.update(list => [...list, newTask]);
}
Avoid heavy logic inside effects
Keep side effects lightweight (logging, analytics, syncing).
Use services for business logic.
Use Signals for local state, RxJS for streams
Signals are great for component-level state.
RxJS still shines for async operations like HTTP requests, event streams, and WebSockets.
Combine with Angular’s new signal inputs (Angular v17+)
Instead of @Input(), you can directly use signals as inputs in child components for better reactivity.
🔹 Why Use Signals?
Performance boost: Fine-grained change detection updates only what’s needed.
Cleaner code: Less boilerplate compared to RxJS.
Future-proof: Signals are part of Angular’s reimagined reactivity model.
✅ Conclusion
Angular Signals bring a paradigm shift in how we manage state and reactivity in Angular. Whether you’re building simple counters or complex dashboards, Signals make your code simpler, faster, and more maintainable.
If you’re already using Angular 16 or later, start experimenting with Signals in your next project — they’re going to play a big role in Angular’s future! 🚀
💡 Pro Tip: If you’re migrating from RxJS, don’t try to replace everything. Start small with component state and gradually expand.
Top comments (0)