Receber por email
← Voltar para o catálogo

web-framework-svelte

Svelte 5 Runes reactivity - $state, $derived, $effect, $props, $bindable, components, snippets, event handling, context API

11estrelas
Atualizado há 7 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add agents-inc/skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/web-framework-svelte/svg)](https://www.skillteca.com.br/skills/web-framework-svelte)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Svelte 5 Patterns

Quick Guide: Svelte 5 uses Runes for explicit reactivity. Use $state for reactive variables, $derived for computed values, $effect only as an escape hatch. Use snippets instead of slots. Use callback props instead of event dispatchers. Keep components small and composable.

<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST use Svelte 5 Runes syntax — NOT Svelte 4 patterns like export let, $:, or stores for component state)

(You MUST use $derived for computed values — NEVER use $effect to synchronize state)

(You MUST use snippets ({#snippet} / {@render}) instead of slots (<slot>))

(You MUST use callback props (onclick, onsomething) instead of createEventDispatcher)

(You MUST use $state.raw() for large objects/arrays that are replaced, not mutated)

(You MUST use createContext for type-safe context instead of raw setContext/getContext with string keys)

</critical_requirements>

Auto-detection: Svelte 5, Runes, $state, $derived, $effect, $props, $bindable, $inspect, .svelte, snippet, @render, createContext, getContext, setContext, $state.raw, $state.eager, $derived.by, $effect.pre, ClassValue

When to use:

  • Building Svelte 5 components with Runes reactivity
  • Managing component state with $state and computed values with $derived
  • Creating reusable markup with snippets (replacing slots)
  • Handling events with native event attributes and callback props
  • Sharing state across components with context API
  • Two-way binding with $bindable props

Key patterns covered:

  • Runes: $state, $derived, $effect, $props, $bindable, $inspect
  • Component composition with snippets and {@render}
  • Event handling with native attributes and callback props
  • Context API with createContext for type-safe cross-component state
  • Class-based reactive state with $state fields
  • Deep vs shallow reactivity ($state vs $state.raw)

When NOT to use:

  • Meta-framework-specific patterns (routing, load functions, form actions) — use the corresponding meta-framework skill
  • Svelte 4 patterns (export let, $: reactive statements, <slot>, createEventDispatcher)
  • Server-side logic (use your meta-framework's server hooks and routes)

Detailed Resources:

  • For decision frameworks and anti-patterns, see [reference.md](reference.md)

Runes & Reactivity:

  • [examples/core.md](examples/core.md) - $state, $derived, $effect, $props, $bindable, component patterns

Component Patterns:

  • [examples/snippets.md](examples/snippets.md) - Snippet blocks, {@render}, passing snippets as props, replacing slots
  • [examples/events.md](examples/events.md) - Event handling, component events via callback props, event modifiers

Advanced:

  • [examples/advanced.md](examples/advanced.md) - $inspect, context API, $state.raw, $state.eager, class-based state, shared state modules

<philosophy>

Philosophy

Svelte 5 introduces Runes — a set of primitives that bring explicit, fine-grained reactivity to Svelte. Unlike Svelte 4's compiler magic ($:, export let), Runes make reactivity visible and portable across .svelte files, .ts files, and class definitions.

Core principles:

  1. Explicit reactivity — Runes ($state, $derived, $effect) make reactive declarations visible. No hidden compiler transformations.
  2. Derived over effects — Compute values with $derived, not $effect. Effects are escape hatches, not primary tools.
  3. Deep reactivity by default — $state creates deeply reactive proxies for objects/arrays. Mutations are tracked automatically.
  4. Snippets replace slots — {#snippet} blocks are more powerful, typed, and composable than <slot> elements.
  5. Callback props replace event dispatchers — Pass onsomething callback props instead of using createEventDispatcher.
  6. Compile-time optimization — Svelte compiles components to efficient imperative code. No virtual DOM diffing at runtime.

When to use Svelte 5 Runes:

  • All new Svelte components (Runes are the default in Svelte 5)
  • Reactive state in .svelte.ts or .svelte.js files
  • Class-based state with reactive fields
  • Any computed value that depends on reactive state

When NOT to use:

  • Non-reactive constants (use plain const or let)
  • Server-side code that doesn't need reactivity
  • Meta-framework concerns (routing, load functions, server hooks) — use the corresponding meta-framework skill
  • Svelte 4 patterns — export let, $:, stores for component state, <slot>, createEventDispatcher

</philosophy>

<patterns>

Core Patterns

Pattern 1: Reactive State with $state

Use $state to declare reactive variables. Updates to $state variables automatically trigger UI re-renders.

<!-- counter.svelte -->
<script lang="ts">
  let count = $state(0);
  const STEP = 5;

  function increment() {
    count += 1;
  }

  function incrementByStep() {
    count += STEP;
  }
</script>

<button onclick={increment}>
  Count: {count}
</button>
<button onclick={incrementByStep}>
  +{STEP}
</button>

Why good: Explicit reactive declaration, named constants for magic numbers, plain function event handlers

<!-- BAD: Svelte 4 style -->
<script>
  let count = 0; // Not explicitly reactive in Svelte 5 mode
  $: doubled = count * 2; // Svelte 4 reactive statement
</script>

Why bad: $: is Svelte 4 syntax deprecated in Svelte 5, implicit reactivity is confusing and non-portable

Deep Reactivity

$state creates deep proxies for objects and arrays — mutations are tracked automatically:

<script lang="ts">
  interface Todo {
    done: boolean;
    text: string;
  }

  let todos = $state<Todo[]>([
    { done: false, text: 'Learn Svelte 5' }
  ]);

  function addTodo(text: string) {
    todos.push({ done: false, text }); // Mutation tracked!
  }

  function toggleTodo(index: number) {
    todos[index].done = !todos[index].done; // Deep mutation tracked!
  }
</script>

Why good: No need for immutable update patterns, array methods like .push() trigger reactivity, property mutations tracked deeply

Pattern 2: Computed Values with $derived

Use $derived for values that depend on other reactive state. Never use $effect to synchronize state.

<script lang="ts">
  let count = $state(0);

  // Simple expression
  let doubled = $derived(count * 2);

  // Complex computation with $derived.by
  let stats = $derived.by(() => {
    const isEven = count % 2 === 0;
    const isPositive = count > 0;
    return { isEven, isPositive };
  });
</script>

<p>{count} doubled is {doubled}</p>
<p>Even: {stats.isEven}, Positive: {stats.isPositive}</p>

Why good: Automatically recalculates when dependencies change, no side effects, push-pull reactivity avoids unnecessary recalculations

<!-- BAD: Using $effect to synchronize state -->
<script lang="ts">
  let count = $state(0);
  let doubled = $state(0);

  $effect(() => {
    doubled = count * 2; // WRONG: Use $derived instead
  });
</script>

Why bad: $effect for derived state creates unnecessary reactive subscriptions, runs after DOM update (timing issues), harder to reason about data flow

Pattern 3: Component Props with $props

Use $props to declare component inputs. Supports destructuring, defaults, rest props, and TypeScript.

<!-- user-card.svelte -->
<script lang="ts">
  interface Props {
    name: string;
    email: string;
    role?: string;
    class?: string;
  }

  let { name, email, role = 'member', ...rest }: Props = $props();

  // Derived from props — updates when props change
  let initials = $derived(
    name.split(' ').map(n => n[0]).join('').toUpperCase()
  );
</script>

Compartilhar X LinkedIn