2.6 KiB
Svelte 5 Patterns and Rules
This document contains Svelte-specific implementation rules.
Only read this file when modifying Svelte components, routes, or Svelte-specific logic.
Svelte Version
This project uses:
- SvelteKit 2
- Svelte 5
- runes mode
Always use:
- $state()
- $derived()
- $effect()
- $props()
Do not use legacy stores:
- writable()
- readable()
- derived()
Component Props
Always destructure $props() with defaults.
Preferred pattern:
let { record = {} as Record<string, unknown>, fieldErrors = {} as Record<string, string>, isSuper = false }: { record?: Record<string, unknown>; fieldErrors?: Record<string, string>; isSuper?: boolean; } = $props();
Do not assume props exist.
State Synchronization
IMPORTANT:
Do not initialize $state from props when the prop can change.
Incorrect:
let name = $state(record.name);
This only captures the initial value.
Correct:
let name = $state('');
$effect(() => { name = String(record.name ?? ''); });
Use $effect whenever component state needs to follow changing props.
Effect Ordering
$effect blocks execute in declaration order.
When multiple effects modify related state:
- Reset state first.
- Populate state second.
- Perform dependent calculations afterward.
Example:
let dirty = $state(false);
$effect(() => { dirty = false; });
$effect(() => { name = String(record.name ?? ''); });
This ensures a new record starts clean.
Select Inputs
IMPORTANT:
Do not use bind:value on select elements whose values are synchronized through $effect.
Incorrect:
OneThis can fail to update correctly.
Use:
<select onchange={(e) => frequency = e.currentTarget.value}> <option value="1" selected={frequency === '1'}> One
Use selected on options.
Input Elements
Text inputs are different.
This is acceptable:
bind:value works correctly with normal input elements.
Forms
Admin forms use:
- $state for field values
- $effect for prop synchronization
- oninput for dirty tracking
- use:enhance for submission
Example:
SaveAvoid Unnecessary State
Prefer:
$derived()
for values computed from other state.
Use:
$state()
only for values that change independently.
Component Changes
Before modifying a component:
- Read the entire component.
- Find similar components.
- Follow existing patterns.
- Avoid introducing new abstractions unless necessary.
Small, consistent changes are preferred.