Runes are Svelte 5’s unified reactivity primitives — compiler-level signals that replace the Svelte 4 let / export let / $: / store ecosystem. They work in .svelte files and .svelte.js / .svelte.ts modules.

$state

$state is the foundation of Svelte 5 reactivity. It transforms ordinary variables into reactive state — when the value changes, the UI updates automatically.

<script>
  let count = $state(0)
</script>
<button onclick={() => count++}>Clicks: {count}</button>

$state deeply proxies arrays and objects, meaning nested property access is reactive. Use $state.raw() to opt out of deep reactivity for performance with large immutable data. Use $state.snapshot() to get a non-reactive copy of reactive state.

$derived

$derived creates computed values that update automatically when their dependencies change. It is the rune replacement for $: derived declarations.

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

Use $derived.by() for multi-statement computations. Derived values are read-only and synchronously computed — no stale data, no manual subscription management.

$effect

$effect runs side effects in response to state changes. It is the rune replacement for $: side-effect statements and lifecycle-based patterns.

<script>
  let count = $state(0)
  $effect(() => {
    console.log('Count changed to', count)
  })
</script>

$effect is not componentDidMount — it runs whenever its tracked dependencies change, not just once. Use $effect.root() for manual lifecycle management and $effect.pre() to run effects before DOM updates.

$props

$props declares component inputs as a destructured object. It replaces export let from Svelte 4.

<script>
  let { name, age = 18, ...rest } = $props()
</script>

All props are reactive by default. Default values are used when no prop is passed. Rest properties capture any additional props passed to the component.

$bindable

$bindable marks a prop as eligible for two-way binding with bind:. By default, props are one-way (parent to child). Adding $bindable() to a prop declaration allows bind:propName on the parent side.

<script>
  let { value = $bindable() } = $props()
</script>

$inspect

$inspect logs reactive values for debugging, firing whenever the tracked value changes. It is a development-only tool that self-removes in production builds.

<script>
  let count = $state(0)
  $inspect(count)
</script>

$host

$host is used in the context of Svelte 5 custom elements. It returns the host element reference, enabling access to the custom element’s DOM API.

Fine-Grained Reactivity

Svelte 5’s runes provide fine-grained reactivity at the variable level, not the component level. This means:

  • Only the specific DOM nodes that depend on a reactive value update
  • No virtual DOM, no diffing — direct DOM updates
  • Reactive values work seamlessly across .svelte.js/.svelte.ts module boundaries
  • Class instances with $state fields are fully reactive

See Also