iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Reactivity (runes)

Svelte 5 ships runes — \$state, \$derived, \$effect. They look like simple function calls but the compiler rewrites them into fine-grained reactive updates. The model is “assignment IS the reaction.”

state / derived / effect runes

EXAMPLE
<script>
    // 1) $state — reactive variable
    let count = $state(0);
    let user  = $state({ name: 'Ada', email: '' });

    // 2) Mutate normally — Svelte tracks the assignment
    function inc()  { count++; }
    function rename(n) { user.name = n; }

    // 3) $derived — like Vue computed, cached, only recomputes on dependency change
    let double  = $derived(count * 2);
    let valid   = $derived(user.email.includes('@'));

    // 4) $derived.by — for complex multi-line derivations
    let summary = $derived.by(() => {
        const len = user.name.length;
        const ok  = valid;
        return ok ? `${user.name} (${len} chars, valid email)` : 'invalid';
    });

    // 5) $effect — side effects, runs after the DOM updates
    $effect(() => {
        document.title = `Count: ${count}`;
    });

    // Effect with cleanup
    $effect(() => {
        const id = setInterval(() => count++, 1000);
        return () => clearInterval(id);
    });

    // 6) $state.raw — opt out of deep reactivity (perf)
    let bigList = $state.raw([]);    // assigning replaces; mutations are NOT tracked
    function loadList(arr) { bigList = arr; }

    // 7) Props with the new $props rune
    let { initial = 0, onChange } = $props();

    // 8) Two-way binding — bindable rune
    let value = $state('');
    // <input bind:value />
</script>

<!-- Template -->
<button onclick={inc}>Count is {count}, double is {double}</button>
<input bind:value={user.email} />
<p>{summary}</p>

<!-- 9) Migrating from Svelte 4 -->
<!-- Svelte 4:  let count = 0; $: double = count * 2; -->
<!-- Svelte 5:  let count = $state(0); let double = $derived(count * 2); -->

<!-- 10) Why runes -->
<!-- The old `let count = 0` was magically reactive only in .svelte files,
     which broke when you exported reactive state to a .js helper. Runes
     work consistently in .svelte and .svelte.js files. -->

Why it matters

Runes make state explicit. The same \$state / \$derived work in both .svelte components and plain .svelte.js modules — finally a clean way to extract reusable reactive logic outside components.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Svelte 5 — runes are first-class reactivity.
// $state, $derived, $effect, $props
Try it Yourself »

Exercise

Declare reactive state (Svelte 5).

let count = (0);

Test yourself

Q1. In Svelte 5, reactive state is declared with…
Q2. Derived/computed values use…
Q3. Side effects (auto-rerun on dep change) use…

Discussion

Loading…