{"dataset":{"id":"00000000-0000-0000-0000-000000000022","slug":"svelte-best-practices","name":"Svelte best practices","description":"Source-linked guidance on Svelte 5 fundamentals: reactive state with $state, derived values, effects, component props, and event handling. Scoped to Svelte 5; not a SvelteKit or legacy Svelte 4 corpus.","visibility":"public","version":1,"documentCount":5,"publisher":"Koskamo editorial","license":"Original summaries; linked sources retain their own terms.","reviewedAt":"2026-10-04T00:00:00.000Z","readOnly":true,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},"total":5,"documents":[{"title":"Event handling with on attributes","sourceUrl":"https://svelte.dev/docs/svelte/basic-markup#Events","text":"Listen to DOM events with attributes that start with on, such as onclick on a button. Event attributes are case sensitive — onclick listens to the click event while onClick listens to the Click event — which is what allows listening to custom events with uppercase characters. Because events are just attributes, they follow attribute rules: the {onclick} shorthand works and they can be spread. Event attributes always fire after events from bindings, so oninput runs after a bind:value update; ontouchstart and ontouchmove handlers are passive for better scroll performance, and in the rare cases you must prevent those defaults use the on function instead, for example inside an action. To reduce memory footprint and increase performance, Svelte delegates events such as click, input, keydown, and touchstart to a single listener at the application root — so manually dispatched events need { bubbles: true } to reach it, and direct addEventListener calls should avoid stopPropagation. Prefer the on function imported from svelte/events over addEventListener, since it preserves ordering and handles stopPropagation correctly under delegation. Scope: Svelte 5. Reviewed October 4, 2026.","id":"svelte-best-practices:Event handling with on attributes","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},{"title":"Components and props with $props","sourceUrl":"https://svelte.dev/docs/svelte/$props","text":"Component inputs are props, passed like element attributes — <MyComponent adjective=\"cool\" /> — and received with the $props rune, commonly destructured as let { adjective } = $props(). Destructuring supports fallback values (used when the parent omits the prop or passes undefined), renaming for invalid identifiers or keywords like super, and rest properties for the remaining props; fallback values are not turned into reactive state proxies, so mutating a fallback object causes no updates. Prop references update when the parent's value updates, and a child may temporarily reassign a prop for unsaved ephemeral state — but do not mutate props: mutating a regular object prop has no effect, and mutating a reactive state proxy raises an ownership_invalid_mutation warning because the component is mutating state it does not own. Use callback props to communicate changes, or the $bindable rune when parent and child should share the same object. Annotating props with TypeScript or JSDoc is recommended so consumers can discover what to pass; $props.id() (Svelte 5.20.0+) generates an instance-unique ID consistent across hydration for linking elements with for and aria-labelledby. Scope: Svelte 5. Reviewed October 4, 2026.","id":"svelte-best-practices:Components and props with $props","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},{"title":"$effect usage rules","sourceUrl":"https://svelte.dev/docs/svelte/$effect","text":"$effect runs a function when state updates — for calling third-party libraries, drawing on canvas elements, or making network requests — and only in the browser, never during server-side rendering. Treat it as an escape hatch for things like analytics and direct DOM manipulation, not a frequently used tool: do not update state inside effects, which makes code convoluted and often leads to never-ending update cycles, and do not use an effect to synchronise state — use $derived or $derived.by instead. Effects run after the component mounts to the DOM, then in a microtask after state changes; re-runs are batched and happen after DOM updates. Returning a function creates a teardown that runs immediately before the effect re-runs and when the component is destroyed. Dependencies are the reactive values ($state, $derived, $props) read synchronously, including via function calls, during the last run; values read after an await or inside setTimeout are not tracked, so conditional reads change what re-triggers the effect. Use $effect.pre when code must run before DOM updates. Scope: Svelte 5. Reviewed October 4, 2026.","id":"svelte-best-practices:$effect usage rules","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},{"title":"Derived state with $derived and $derived.by","sourceUrl":"https://svelte.dev/docs/svelte/$derived","text":"Derived state is declared with the $derived rune — let doubled = $derived(count * 2) — because component code runs only once at creation, so a plain variable keeps its original value when dependencies change. The expression inside $derived(...) must be free of side-effects; Svelte disallows state changes inside derived expressions. For derivations that do not fit a single expression, $derived.by accepts a function, and $derived(expression) is equivalent to $derived.by(() => expression). Anything read synchronously inside the expression or function body becomes a dependency: when it changes, the derived is marked dirty and recalculated when next read. An await inside the expression is transformed so state read after it is still tracked, and untrack exempts a value from being treated as a dependency. A derived declared with let can be temporarily overridden by reassignment — useful for optimistic UI — whereas prior to Svelte 5.25 deriveds were read-only. Unlike $state, $derived values are left as-is rather than converted to deeply reactive proxies, and class fields can be marked $derived. Scope: Svelte 5. Reviewed October 4, 2026.","id":"svelte-best-practices:Derived state with $derived and $derived.by","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},{"title":"Reactive state with the $state rune","sourceUrl":"https://svelte.dev/docs/svelte/$state","text":"The $state rune creates reactive state: the UI reacts when the value changes. There is no special API for interacting with state — a value like count is just a number, updated like any other variable. When $state wraps an array or a simple object, the result is a deeply reactive state proxy, so property reads and writes, including mutations through methods like array.push(...), trigger granular updates to whatever depends on that specific property. State is proxified recursively until Svelte meets something other than an array or simple object, such as a class instance. Two caveats matter in practice: destructuring a reactive value breaks reactivity, because destructured references are evaluated at the point of destructuring, and class instances are not proxied — instead use $state in class fields or as the first assignment inside the constructor. For objects you do not want deeply reactive, $state.raw declares state that cannot be mutated, only reassigned, and $state.snapshot takes a static snapshot of a proxy; reactive Set, Map, Date, and URL implementations are importable from svelte/reactivity. Scope: Svelte 5. Reviewed October 4, 2026.","id":"svelte-best-practices:Reactive state with the $state rune","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"}]}