patternjavascriptsvelteModerate
Svelte 5 runes: $state, $derived, $effect replace reactive declarations
Viewed 0 times
Svelte 5.0+
svelte5runes$state$derived$effect$propsreactivity model
Error Messages
Problem
Svelte 4's $: reactive declarations and mutable let variables are implicit and hard to understand. Svelte 5 introduces explicit runes that clarify reactivity intent and work in .ts files too.
Solution
Use Svelte 5 runes for explicit reactivity:
<script>
// $state: reactive variable (replaces let)
let count = $state(0);
let user = $state({ name: 'Alice', age: 30 });
// $derived: synchronous computed (replaces $:)
const doubled = $derived(count * 2);
const greeting = $derived(
// $derived.by: for complex derivations
const stats = $derived.by(() => {
return { total: count, average: count / 2 };
});
// $effect: side effect (replaces $: for side effects)
$effect(() => {
document.title =
return () => {
// cleanup — runs before re-executing and on destroy
document.title = 'App';
};
});
// $props: replaces export let (in components)
const { name, size = 'md' } = $props();
</script>
<button onclick={() => count++}>{count}</button>
<script>
// $state: reactive variable (replaces let)
let count = $state(0);
let user = $state({ name: 'Alice', age: 30 });
// $derived: synchronous computed (replaces $:)
const doubled = $derived(count * 2);
const greeting = $derived(
Hello ${user.name});// $derived.by: for complex derivations
const stats = $derived.by(() => {
return { total: count, average: count / 2 };
});
// $effect: side effect (replaces $: for side effects)
$effect(() => {
document.title =
Count: ${count};return () => {
// cleanup — runs before re-executing and on destroy
document.title = 'App';
};
});
// $props: replaces export let (in components)
const { name, size = 'md' } = $props();
</script>
<button onclick={() => count++}>{count}</button>
Why
Runes are explicit compiler signals that work in any context — .svelte files, .ts files, and .svelte.ts files. They make reactive intent clear and allow sharing reactive logic in plain TypeScript files (like custom state classes).
Gotchas
- Runes mode is opt-in per file or per project — mixing Svelte 4 and 5 syntax in one file causes errors
- $state objects have deep reactivity by default — mutations are tracked without reassignment
- $effect.pre runs before DOM updates (like beforeUpdate), $effect runs after
- Arrays and objects in $state use proxies — you can push/splice without reassigning
Code Snippets
Shared reactive class with Svelte 5 runes
// Shared reactive state in a .svelte.ts file
class Counter {
count = $state(0);
doubled = $derived(this.count * 2);
increment() { this.count++; }
}
export const counter = new Counter();Context
When writing Svelte 5 components with the new runes reactivity model
Revisions (0)
No revisions yet.