$derived — Computed Values
React’s useMemo memoises expensive computations — but you must declare every reactive input in the dependency array or risk stale values. Svelte 5’s $derived does the same thing without the array: the compiler scans the expression, finds every reactive variable it reads, and re-runs the computation automatically whenever any of them changes.
$derived vs useMemo
Section titled “$derived vs useMemo”function PriceCalc() { const [price, setPrice] = React.useState(100); const [qty, setQty] = React.useState(3);
const total = React.useMemo(() => price * qty, [price, qty]); const withTax = React.useMemo(() => total * 1.07, [total]);
return ( <div> <p>Unit price: {price} — Qty: {qty}</p> <p>Total: {total} — With tax: {withTax.toFixed(2)}</p> <button onClick={() => setQty(q => q + 1)}>+qty</button> </div> );}<script> let price = $state(100); let qty = $state(3);
let total = $derived(price * qty); let withTax = $derived(total * 1.07);</script>
<p>Unit price: {price} — Qty: {qty}</p><p>Total: {total} — With tax: {withTax.toFixed(2)}</p><button onclick={() => qty++}>+qty</button>No [price, qty] dependency array. $derived chains — withTax reads total, which reads price and qty. The compiler builds the entire reactive graph automatically.
$derived.by — multi-step computations
Section titled “$derived.by — multi-step computations”$derived(expr) only accepts a single expression. When the computation needs multiple statements — a filter, reduce, or conditional — use $derived.by(() => { ... return result; }). This maps to useMemo with a multi-statement body.
function FilteredList() { const [items] = React.useState(['apple', 'banana', 'apricot', 'blueberry', 'avocado']); const [query, setQuery] = React.useState('a');
const filtered = React.useMemo(() => { const lower = query.toLowerCase(); return items.filter(item => item.startsWith(lower)); }, [items, query]);
return ( <div> <input value={query} onChange={e => setQuery(e.target.value)} /> <ul>{filtered.map(f => <li key={f}>{f}</li>)}</ul> </div> );}<script> let items = $state(['apple', 'banana', 'apricot', 'blueberry', 'avocado']); let query = $state('a');
let filtered = $derived.by(() => { const lower = query.toLowerCase(); return items.filter(item => item.startsWith(lower)); });</script>
<input bind:value={query} /><ul> {#each filtered as f} <li>{f}</li> {/each}</ul>