Effects in Angular’s new reactivity system let you perform side effects whenever reactive values (signals or computed values) change. Instead of writing logic directly in templates, you attach it to effects that automatically re-run when their dependencies update.
count = signal(0).computed() for pure calculations and effect() for side effects.An effect is created by calling effect() and passing a function that reads one or more signals. Angular automatically tracks those signals and re-runs the function whenever they change.
// Basic effect reacting to a signal change
import { effect, signal } from '@angular/core';
const count = signal(0);
const logEffect = effect(() => {
console.log('Count is now:', count());
});
count.set(5); // Triggers effect
count.update(c => c + 1); // Triggers effect again
count is a signal holding a numeric value.effect() registers a reactive side effect that reads count().count changes, the effect runs and logs the new value.This example shows how an effect can log changes to a counter signal whenever the user clicks a button.
// Angular component using an effect to watch a counter signal
import { Component, effect, signal } from '@angular/core';
@Component({
selector: 'app-root',
template: `<h2>Count: {{ count() }}</h2>
<button (click)="increment()">Increment</button>`
})
export class AppComponent {
count = signal(0);
constructor() {
effect(() => {
console.log(`Count changed: ${this.count()}`);
});
}
increment() {
this.count.update(c => c + 1);
}
}
signal(0) creates a reactive state variable count with initial value 0.effect() reads this.count(), so Angular tracks it as a dependency.increment() is called, count updates and the effect logs the new value.Effects can also be used to handle async operations like fetching data from an API and updating a signal.
// Using an effect to fetch users and keep the UI in sync
import { Component, effect, signal } from '@angular/core';
@Component({
selector: 'user-list',
template: `<h3>Users</h3>
<ul>
<li *ngFor="let user of users()">{{ user.name }}</li>
</ul>`
})
export class UserListComponent {
users = signal<any[]>([]);
constructor() {
effect(async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
this.users.set(await res.json());
});
}
}
users is a signal that stores an array of user objects.effect() performs an async fetch() call to load user data.this.users.set(...).users(), so Angular re-renders the list whenever the signal changes.computed() or regular functions.count() instead of count when reading them..catch() on promises).