signal, computed, effect — and When effect Is the Wrong Answer In short: Three building blocks. The third one causes most of the trouble, and knowing when not to use it is the difference between clean signal code and a tangle. The three building blocks Changing a signal: was removed before signals were finished. Do not look for it. Replace values instead. Two behaviours that explain everything Signals are lazy. A does not run when its sources change. It just marks itself as out of date, and recalculates the next time somebody reads it. A nobody reads never runs at all. This is the opposite of an RxJS , which runs for every value whether anyone uses the result or not. Updates are always consistent. In the code above, uses and , and also uses . Change once, and is worked out exactly once, with matching inputs. There is never a moment where has updated but has not. Hand-written reactive code — and -based syncing — gets this wrong all the time, and it shows up as a flash of wrong numbers on screen. Equality: the thing that silently breaks A signal only tells its readers when the value actually changes , and it compares by identity. For simple values that is exactly right. For objects it means changing something inside is invisible : This is the single most common cause of "my signal is not updating." Same for arrays: You can supply your own comparison when a deep check is genuinely cheaper than the redraw it saves: Use this rarely. A deep comparison on a big object runs on every change, and usually costs more than the redraw it prevents. When is the wrong answer is for pushing values out of Angular into the outside world . That is it. Four fair uses: Everything else is probably a mistake. Three common ones: Mistake 1 — keeping one signal in step with another This creates a second place the truth lives, runs late, and can be changed from elsewhere without anyone noticing. It is a : The rule: if an effect's body is a on another signal, you wanted or . Mistake 2 — fetching data No cancelling, so a slow reply to an old search can overwrite a newer correct one. No waiting for the user to stop typing, so every keystroke sends a request. No loading or error state. That is (lesson 5) or an RxJS pipeline (lesson 4). Mistake 3 — using it like a lifecycle method Same problem as above. If the thing you want is data, it is a resource. If it is a calculation, it is a . Writing to signals inside effects Angular used to require a special flag to write a signal inside an effect. That flag was removed in v19 — writes are allowed by default now. That made the API simpler and made it easier to write the mistakes above. Angular still protects you from endless loops, but "it does not crash" is not the same as "it is right." If you write to a signal inside an effect, be able to say why or does not cover it. There are real cases. They are rarer than the code you find online suggests. Cleanup Effects created in a component are destroyed with it. For anything with its own cleanup, use the cleanup callback: runs before each re-run and once on destroy — so changing closes the old connection before opening the new one. Two related helpers. reads a signal without depending on it: And runs after the page has been updated, for when you need to measure real elements. "But isn't effect() the new ngOnChanges?" It looks like it. It fires when something changes and runs your code. That resemblance is the trap. The difference that matters: was a place Angular invited you to run code . is an exit door — a way for values to leave Angular and reach something that is not reactive. Ask what happens to the result: If it stays inside Angular (another signal, a template, a calculation) → or If it leaves Angular (storage, a chart library, analytics, the console) → That one question settles nearly every case. Why the mistake is expensive. runs after the update that triggered it. So for one frame, your worked-out value is out of date: Set to 200 and the user briefly sees next to a total of . With that state cannot exist . The other half of the myth is "signals mean no lifecycle methods at all." Mostly true, with real exceptions: (or better, ) for cleanup you own, and for anything that measures the page. What really disappears is , and most bodies. The architect's view The clearest way to see what signals buy you is a screen where several values depend on each other — a billing form with line items, quantities, a discount code, tax, and a total. The old shape. Every handler recalculates, and each one is a chance to forget a step: Four handlers, each needing correct knowledge of how everything connects — knowledge that exists only in a developer's head, and has to be re-derived by whoever edits it next. The signal shape — describe the connections once: What changed, on each axis: Correctness. In the first version, a handler can forget a step and the screen shows a stale number with no error. In the second, forgetting is not possible — the connection is stated o…