Rabin R
Angular Tipsintermediate

Prefer computed() over effect() for derived state

Reach for effect() only for side effects — derived values belong in computed(), which stays pull-based and glitch-free.

Introduction

A recurring smell in signal code is using effect() to copy one signal into another. It works, but it makes the value push-based and eagerly recomputed, and it runs outside the reactive graph the template consumes.

computed() is the right tool: it is lazy, memoized, and only recalculates when a dependency it actually read has changed.

The fix

// Avoid: eager, imperative, easy to desync
readonly full = signal('');
constructor() {
  effect(() => this.full.set(`${this.first()} ${this.last()}`));
}

// Prefer: lazy, memoized, no extra signal to keep in sync
readonly full = computed(() => `${this.first()} ${this.last()}`);

When effect IS right

  • Writing to localStorage or the URL when state changes.
  • Imperatively calling a non-signal API (chart redraw, focus).
  • Logging / analytics on a state transition.