## Svelte You **MUST** use the Svelte 5 API unless explicitly tasked to write Svelte 4 syntax. If you don't know about the API yet, below is the most important information about it. Other syntax not explicitly listed like `{#if ...}` blocks stay the same, so you can reuse your Svelte 4 knowledge for these. - to mark something a state you use the `$state` rune, e.g. instead of `let count = 0` you do `let count = $state(0)` - to mark something as a derivation you use the `$derived` rune, e.g. instead of `$: double = count * 2` you do `const double = $derived(count * 2)` - to create a side effect you use the `$effect` rune, e.g. instead of `$: console.log(double)`you do`$effect(() => console.log(double))` - to create component props you use the `$props` rune, e.g. instead of `export let foo = true; export let bar;` you do `let { foo = true, bar } = $props();` - when listening to dom events do not use colons as part of the event name anymore, e.g. instead of `` you do `` ### What are runes? - Runes are built-in Svelte keywords (prefixed with `$`) that control the compiler. For example, you write `let message = $state('hello');` in a `.svelte` file. - Do **NOT** treat runes like regular functions or import them; instead, use them as language keywords. _In Svelte 4, this syntax did not exist—you relied on reactive declarations and stores; now runes are an integral part of the language._ ### $state - `$state` creates reactive variables that update the UI automatically. For example: ```svelte ``` - Do **NOT** complicate state management by wrapping it in custom objects; instead, update reactive variables directly. _In Svelte 4, you created state with let, e.g. `let count = 0;`, now use the $state rune, e.g. `let count = $state(0);`._ - Arrays and objects become deeply reactive proxies. For example: ```js let todos = $state([{ done: false, text: 'add more todos' }]); todos[0].done = !todos[0].done; ``` - Do **NOT** destructure reactive proxies (e.g., `let { done } = todos[0];`), as this breaks reactivity; instead, access properties directly. - Use `$state` in class fields for reactive properties. For example: ```js class Todo { done = $state(false); text = $state(''); reset = () => { this.text = ''; this.done = false; }; } ``` ### $state.raw - `$state.raw` creates shallow state where mutations are not tracked. For example: ```js let person = $state.raw({ name: 'Heraclitus', age: 49 }); // Instead of mutating: // person.age += 1; // NO effect person = { name: 'Heraclitus', age: 50 }; // Correct way to update ``` - Do **NOT** attempt to mutate properties on raw state; instead, reassign the entire object to trigger updates. ### $state.snapshot - `$state.snapshot` produces a plain object copy of reactive state. For example: ```svelte ``` - **ONLY** use this if you are told there's a problem with passing reactive proxies to external APIs. ### Passing state into functions - Pass-by-Value Semantics: Use getter functions to ensure functions access the current value of reactive state. For example: ```js function add(getA, getB) { return () => getA() + getB(); } let a = 1, b = 2; let total = add( () => a, () => b ); console.log(total()); ``` - Do **NOT** assume that passing a reactive state variable directly maintains live updates; instead, pass getter functions. _In Svelte 4, you often used stores with subscribe methods; now prefer getter functions with `$state` / `$derived` instead._ ### $derived - `$derived` computes reactive values based on dependencies. For example: ```svelte ``` - Do **NOT** introduce side effects in derived expressions; instead, keep them pure. _In Svelte 4 you used `$:` for this, e.g. `$: doubled = count * 2;`, now use the $derived rune instead, e.g `let doubled = $derived(count * 2);`._ #### $derived.by - Use `$derived.by` for multi-line or complex logic. For example: ```svelte ``` - Do **NOT** force complex logic into a single expression; instead, use `$derived.by` to keep code clear. #### Overriding derived values - You can reassign a derived value for features like optimistic UI. It will go back to the `$derived` value once an update in its dependencies happen. For example: ```svelte ``` - Do **NOT** try to override derived state via effects; instead, reassign directly when needed. _In Svelte 4 you could use `$:` for that, e.g. `$: likes = post.likes; likes = 1`, now use the `$derived` instead, e.g. `let likes = $derived(post.likes); likes = 1;`._ ### $effect - `$effect` executes functions when reactive state changes. For example: ```svelte ``` - Do **NOT** use `$effect` for state synchronization; instead, use it only for side effects like logging or DOM manipulation. _In Svelte 4, you used reactive statements (`$:`) for similar tasks, .e.g `$: console.log(size)`; now use the `$effect` rune instead, e.g. `$effect(() => console.log(size))` ._ #### Understanding lifecycle (for $effect) - Effects run after the DOM updates and can return teardown functions. For example: ```svelte ``` - **Directive:** Do **NOT** ignore cleanup; instead, always return a teardown function when needed. #### $effect.pre - `$effect.pre` works like `$effect` with the only difference that it runs before the DOM updates. For example: ```svelte ``` - Do **NOT** use `$effect.pre` for standard post-update tasks; instead, reserve it for pre-DOM manipulation like autoscrolling. #### $effect.tracking - `$effect.tracking` indicates if code is running inside a reactive context. For example: ```svelte ``` - Do **NOT** misuse tracking information outside its intended debugging context; instead, use it to enhance reactive debugging. _In Svelte 4, no equivalent existed; now this feature offers greater insight into reactivity._ #### $effect.root - `$effect.root` creates a non-tracked scope for nested effects with manual cleanup. For example: ```svelte ``` - Do **NOT** expect root effects to auto-cleanup; instead, manage their teardown manually. _In Svelte 4, manual cleanup required explicit lifecycle hooks; now `$effect.root` centralizes this control._ ### $props - Use `$props` to access component inputs. For example: ```svelte
This component is {adjective}
``` - Do **NOT** mutate props directly; instead, use callbacks or bindable props to communicate changes. _In Svelte 4, props were declared with `export let foo`; now you use `$props` rune, e.g. `let { foo } = $props()`._ - Declare fallback values via destructuring. For example: ```js let { adjective = 'happy' } = $props(); ``` - Rename props to avoid reserved keywords. For example: ```js let { super: trouper } = $props(); ``` - Use rest syntax to collect all remaining props. For example: ```js let { a, b, ...others } = $props(); ``` #### $props.id() - Generate a unique ID for the component instance. For example: ```svelte ``` - Do **NOT** manually generate or guess IDs; instead, rely on `$props.id()` for consistency. ### $bindable - Mark props as bindable to allow two-way data flow. For example, in `FancyInput.svelte`: ```svelte ``` - Do **NOT** overuse bindable props; instead, default to one-way data flow unless bi-directionality is truly needed. _In Svelte 4, all props were implicitly bindable; in Svelte 5 `$bindable` makes this explicit._ ### $host - Only available inside custom elements. Access the host element for custom event dispatching. For example: ```svelte ``` - Do **NOT** use this unless you are explicitly tasked to create a custom element using Svelte components ### {#snippet ...} - **Definition & Usage:** Snippets allow you to define reusable chunks of markup with parameters inside your component. _Example:_ ```svelte {#snippet figure(image)}hello {name}! {message}!
{/snippet} {@render hello('alice')} ``` - **Scope Limitations:** Snippets are only accessible within their lexical scope; siblings and child blocks share scope, but nested snippets cannot be rendered outside. _Usage caution:_ Do **NOT** attempt to render a snippet outside its declared scope. ### Passing snippets to components - **As Props:** Within a template, snippets are first-class values that can be passed to components as props. _Example:_ ```svelte {#snippet header()}hi {y}
hi {y}
{/snippet}{a} + {b} = {a + b}
{/snippet} {@render sum(1, 2)} ``` - Do **NOT** call snippets without parentheses when parameters are required; instead, always invoke the snippet correctly. _In Svelte 4, you used slots for this, e.g. `