Derived values keep the UI consistent without duplicating state or writing manual sync code.
When a value can be computed from other state, declare it with `$derived`:
let count = $state(0);
let doubled = $derived(count * 2);Svelte tracks which state the expression reads and recalculates it when one of those changes. Derived values are lazy and cached: recomputed only when read after a dependency changed.
For logic that needs statements, use `$derived.by` with a function:
let stats = $derived.by(() => {
let done = 0;
for (const t of todos) if (t.done) done++;
return { done, open: todos.length - done };
});Rules and tips:
- The expression must be free of side effects; Svelte disallows state changes inside a derived.
- Dependencies are whatever is read synchronously inside it.
- If the new value is identical (
===) to the old one, dependents don't update. - Since Svelte 5.25 you can temporarily assign to a derived (for optimistic UI); it recalculates again when its dependencies change.
The common mistake from other frameworks is to use an effect that writes to another $state whenever something changes. If you can express a value as a function of other state, $derived is simpler, faster and never out of sync.
Example
<script>
let todos = $state([
{ text: 'write', done: true },
{ text: 'test', done: false },
]);
let filter = $state('all');
let visible = $derived(
filter === 'all' ? todos : todos.filter((t) => t.done === (filter === 'done'))
);
let stats = $derived.by(() => {
const done = todos.filter((t) => t.done).length;
return { done, open: todos.length - done };
});
</script>
<select bind:value={filter}>
<option>all</option><option>done</option><option>open</option>
</select>
<p>{stats.done} done, {stats.open} open</p> <!-- 1 done, 1 open -->
<ul>{#each visible as t}<li>{t.text}</li>{/each}</ul>Remember
$derived(expr)recomputes when state it reads changes$derived.by(() => {...})for multi-statement logic- Prefer derived over effects that copy state around
Watch out for
- Using
$effectto set one$statefrom another; that is exactly what$derivedis for.