Svelte 5 introduces Runes, an explicit set of compiler primitives that bring fine-grained reactivity directly into standard JavaScript logic without virtual DOM overhead or complex dependency arrays.
Interactive Rune Playground
Try updating the counter below to see Svelte 5’s $state and $derived signal calculations update instantly:
Interactive $state & $derived Demo
✨ Mutating count directly updates these derived values in fine-grained
DOM signals without re-rendering the surrounding template tree.
1. Fine-Grained Reactive State with $state
State in Svelte 5 is declared using the $state() rune. Unlike framework implementations that require explicit setter functions (setState), Svelte 5 allows direct mutations while surgical DOM updates happen behind the scenes:
Reactive State Mutation
Comparing React 19 useState setters with Svelte 5 $state signals.
2. Derived Computations with $derived
Use $derived() to calculate reactive values automatically. Derived signals are memoized and only re-evaluate when their underlying dependencies change:
<script>
let count = $state(5);
let double = $derived(count * 2);
let quad = $derived(double * 2);
</script>
<p>Count: {count} | Double: {double} | Quad: {quad}</p> 3. Side Effects with $effect
The $effect() rune handles side effects and synchronization with external systems. It tracks reactive reads automatically and runs after the DOM updates:
<script>
let query = $state('');
$effect(() => {
console.log('Search query updated:', query);
// Optional teardown function runs before effect re-executes
return () => {
console.log('Cleaning up previous search...');
};
});
</script> 4. Shared Universal State (.svelte.ts)
Runes aren’t restricted to Svelte components. You can declare reactive state in standard .svelte.ts files and share it across your application:
// src/lib/stores/cart.svelte.ts
export class CartStore {
items = $state<string[]>([]);
totalCount = $derived(this.items.length);
addItem(item: string) {
this.items.push(item); // Deep reactivity updates all subscribers
}
}
export const cart = new CartStore(); Key Core Advantages
- Universal Usage: Runes work seamlessly inside
.sveltecomponents and.svelte.tsmodules. - No Dependency Arrays: Unlike React’s
useEffectoruseMemo,$effectand$derivedtrack read properties automatically. - Deep Mutation Tracking: Object property updates (
user.name = 'Alex') and array mutations (items.push()) trigger surgical DOM patches natively.