02 - Derived ($derived)

What is $derived?

$derived() creates computed values that automatically update when their dependencies change. It's read-only — you can't assign to a derived value directly.

Svelte 4 (Legacy)

<script>
let count = 0;
$: doubled = count * 2;           // single expression
$: {                                // block of code
  console.log(count);
  doubled = count * 2;
}
</script>

Svelte 5

<script>
let count = $state(0);
let doubled = $derived(count * 2);              // single expression
let total = $derived.by(() => {                 // block of code
  console.log(count);
  return count * 2;
});
</script>

The difference: $: was used for both side effects and computed values, making intent unclear. Svelte 5 separates them — $derived for computed values, $effect for side effects.

Basic Usage

$derived() takes a single expression. Dependencies are tracked automatically — any $state referenced inside is a dependency.

<!-- src/lib/components/Counter.svelte -->
<script>
let count = $state(0);
let doubled = $derived(count * 2);       // updates when count changes
let quadrupled = $derived(doubled * 2);  // can chain derived values
</script>

<p>Count: {count}</p>
<p>Doubled: {doubled}</p>
<p>Quadrupled: {quadrupled}</p>

With Strings

<script>
let firstName = $state('John');
let lastName = $state('Doe');
let fullName = $derived(`${firstName} ${lastName}`);  // updates when either changes
</script>

$derived.by() — Multi-line Logic

Use $derived.by() when you need more than a single expression — loops, conditionals, intermediate variables, etc. It takes a function that returns the computed value.

<script>
let numbers = $state([1, 2, 3, 4, 5]);

let sum = $derived.by(() => {
  let total = 0;
  for (let n of numbers) {
    total += n;
  }
  return total;
});

let average = $derived(sum / numbers.length);
</script>

Key Points

  • Replaces Svelte 4's $: for computed values
  • $derived(expression) for single expressions, $derived.by(() => { ... }) for multi-line logic
  • Automatically tracks dependencies — any $state used inside is a dependency
  • Read-only — you can't assign to a derived value
  • Can chain: a derived value can depend on another derived value

Interactive Example

<script>
let count = $state(0);
let doubled = $derived(count * 2);
let quadrupled = $derived(doubled * 2);

let firstName = $state('John');
let lastName = $state('Doe');
let fullName = $derived(`${firstName} ${lastName}`);

let numbers = $state([1, 2, 3, 4, 5]);
let sum = $derived.by(() => {
  let total = 0;
  for (let n of numbers) {
    total += n;
  }
  return total;
});
let average = $derived(sum / numbers.length);
</script>

<div>
  <h2>02 - Derived Example</h2>
  
  <div>
    <h3>Simple Derived</h3>
    <button onclick={() => count++}>Count: {count}</button>
    <p>Doubled: {doubled}</p>
    <p>Quadrupled: {quadrupled}</p>
  </div>
  
  <div>
    <h3>String Derived</h3>
    <input bind:value={firstName} placeholder="First name" />
    <input bind:value={lastName} placeholder="Last name" />
    <p>Full name: {fullName}</p>
  </div>
  
  <div>
    <h3>Complex Derived (using $derived.by)</h3>
    <p>Numbers: {numbers.join(', ')}</p>
    <button onclick={() => numbers.push(numbers.length + 1)}>Add Number</button>
    <button onclick={() => numbers.pop()}>Remove Last</button>
    <p>Sum: {sum}</p>
    <p>Average: {average.toFixed(2)}</p>
  </div>
</div>

<style>
div { margin: 20px; }
h3 { margin-top: 20px; }
button, input { margin: 5px; }
</style>