Derived State
Two more runes complete Svelte's reactivity core. $derived computes a value from other reactive state and keeps it up to date automatically — the counterpart to Vue's computed, Angular's computed signal, and React's useMemo. $effect runs a side effect whenever the state it reads changes — the counterpart to watch/useEffect. Both, like $state, track their dependencies automatically.
$derived — A Computed Value
$derived(price * quantity) creates a value that automatically recalculates whenever price or quantity changes. Notice the syntax is even lighter than the others: you pass the expression itself, not a function returning it (no () =>). It's read as a plain variable ({total}), just like $state. Like Vue's computed and Angular's computed, it's cached (only recomputes when a dependency changes) and its dependencies are auto-tracked — no dependency array like React's useMemo.
$derived.by — For Multi-Line Logic
When the derivation needs more than a single expression, $derived.by(() => {...}) takes a function with a return — useful for filtering, conditionals, or any multi-step computation. This is the natural home for "filter a list before rendering it," the same pattern seen in Vue's computed filter and React's filter-before-map.
$effect — Running a Side Effect
$effect(() => {...}) runs its function after the component mounts, then again whenever any reactive value it reads changes — automatically tracked, no dependency list. This is for genuine side effects: logging, syncing to localStorage, manually touching the DOM or a third-party library. It's the equivalent of React's useEffect with auto-detected dependencies, or Vue's watchEffect.
Effect Cleanup
Returning a function from an $effect gives a cleanup function — run before the effect re-runs, and when the component is destroyed. This is exactly React's useEffect cleanup return, used the same way: anything that "starts" something ongoing (a timer, a listener, a subscription) returns its matching "stop." This is also how you handle teardown that the other frameworks put in a separate lifecycle hook (Vue's onUnmounted, Angular's ngOnDestroy).
$effect to set one piece of state from another ($effect(() => { doubled = count * 2 })). That's almost always a $derived in disguise, and the $derived version is simpler, cached, and avoids extra re-render cycles. The same rule as Vue's watch-vs-computed: deriving a value → $derived; doing something with a side effect → $effect. Svelte will even warn you about some of these cases.
$: total = price * quantity for derivations and $: console.log(count) for effects — the same $: prefix doing double duty, which was a frequent source of confusion. Svelte 5 split them into two clearly-named runes ($derived and $effect). If you see $: in a tutorial, that's the old combined form.
| Svelte 5 | Vue | React | Angular |
|---|---|---|---|
| $derived(expr) | computed(() => ...) | useMemo (dep array) | computed() signal |
| $derived.by(() => {...}) | computed(() => {...}) | useMemo | computed() |
| $effect(() => {...}) | watchEffect | useEffect (auto) | effect() signal |
| return cleanup from $effect | onUnmounted / watch stop | cleanup return | ngOnDestroy |
Coding Challenges
Build a component with firstName and lastName $state values and a fullName $derived combining them, with inputs to edit each — confirming fullName updates automatically.
📄 View solutionBuild a todo list with a "show completed" checkbox, using $derived.by to compute the visible todos based on the checkbox, then render that filtered list.
📄 View solutionBuild a component with a count $state and an $effect that persists count to localStorage on every change, reading the saved value back as the initial value so it survives a refresh — plus a separate $effect with a setInterval and a cleanup return.
📄 View solutionChapter 3 Quick Reference
- $derived(expr) — a cached, auto-tracked computed value; pass the expression, not a function
- $derived.by(() => {...}) — the function form for multi-line / conditional logic
- $effect(() => {...}) — runs a side effect on mount and whenever read state changes (auto-tracked)
- Return a function from
$effectfor cleanup (= React's useEffect cleanup) - Rule of thumb: deriving a value → $derived; a side effect → $effect
- These split Svelte 4's combined
$:reactive statements into two clear runes - Next chapter: bindings and events — bind:value, event handlers, class:/style: directives