All topics
Stateintermediate

Effects in Angular

Explain effect() as the mechanism for running side effects in response to signal changes.

effect() runs a function whenever any Signal it reads changes, and it exists specifically for side effects — things that shouldn't be modeled as a derived value (which is what computed() is for), like logging, synchronizing state to localStorage, manually manipulating a non-Angular-managed DOM element, or triggering an analytics call whenever a piece of state changes. Interviewers ask about this to check whether you understand the important distinction Angular draws between computed() (pure derivation, returns a value) and effect() (side effects, returns nothing).

computed() is like a thermometer's digital readout — a pure, derived reflection of the current temperature. effect() is like a smart thermostat's furnace kicking on in response to that same temperature reading — a genuine side effect triggered by the value, not a value itself.

Key Concepts

1
Like computed(), an effect() automatically tracks whichever Signals it reads during its execution and re-runs whenever any of those tracked dependencies change — the same automatic dependency-tracking mechanism, just applied to run arbitrary code rather than to produce a memoized value.
computed()effect()
2
A crucial and frequently-tested rule is that effects should not, in general, write to Signals they also read, since that pattern easily leads to infinite reactive loops (the effect changes a Signal, which re-triggers the same effect, which changes it again). Angular actually throws a runtime error by default if an effect writes to a Signal synchronously within itself during that same execution, specifically to catch this class of bug early — though allowSignalWrites (a legacy escape hatch, generally discouraged) exists for narrow cases that genuinely need it.
allowSignalWrites
3
A well-rounded interview answer emphasizes that effect() should be reached for sparingly — many things that look like they need an effect (like updating a derived value) are actually better expressed as a computed() signal instead, and Angular's own guidance explicitly nudges developers toward preferring computed()/template bindings over effect() wherever the goal is really just producing a derived value rather than a genuine external side effect.
effect()computed()