computed() & effect()

Derive State & React to Changes

computed() & effect()

computed() builds a signal from other signals; effect() runs code whenever its dependencies change.

4 min read Level 2/5 #angular#signals#reactivity
What you'll learn
  • Build a computed signal from other signals
  • Use effect() for side effects
  • Convert an Observable to a signal with toSignal

signal() gives you a writable value. computed() derives a read-only value from other signals. effect() runs code whenever the signals it touches change. Together they give you a tiny reactive runtime — no RxJS required.

computed — derived state

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

@Component({
  selector: 'app-profile',
  standalone: true,
  template: `<p>{{ fullName() }}</p>`,
})
export class ProfileComponent {
  first = signal('Ada');
  last = signal('Lovelace');
  fullName = computed(() => `${this.first()} ${this.last()}`);
}

fullName() recomputes only when first or last change — and only when something actually reads it.

effect — side effects

effect() is for cases where reading a signal should trigger something outside the framework — logging, syncing to localStorage, calling an imperative API.

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

@Component({ selector: 'app-counter', standalone: true, template: `{{ count() }}` })
export class CounterComponent {
  count = signal(0);

  constructor() {
    effect(() => {
      localStorage.setItem('count', String(this.count()));
    });
  }
}

Effects run after the first render and again whenever their dependencies change. They are cleaned up automatically when the component is destroyed.

Bridge Observables in

toSignal wraps any Observable into a signal — handy for HTTP results or router data.

import { toSignal } from '@angular/core/rxjs-interop';

user = toSignal(this.users.getCurrent(), { initialValue: null });
isLoading = computed(() => this.user() === null);

Use signal() for state, computed() for derivations, effect() for side effects — that single mental model carries you through most components.

resource() & httpResource() →