Skip to main content

svelte-patterns

Common Svelte patterns, best practices, and mistakes to avoid

Quellinformationen

Repository
code-yeongyu/sisyphus-private
Letzte Quellaktivität
20. Oktober 2025 um 01:49
Erkannte Sprache von SKILL.md
Englisch
Sterne
19
Forks
2

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
svelte-patterns
description
Common Svelte patterns, best practices, and mistakes to avoid
# Svelte Patterns and Best Practices This skill covers common component patterns, frequently made mistakes, best practices, and migration tips for Svelte development. ## Component Patterns ### Prop Patterns ```svelte <!-- Basic props with defaults --> <script> let { title = 'Default Title', subtitle, isActive = false, items = [] } = $props(); </script> <h1>{title}</h1> {#if subtitle} <h2>{subtitle}</h2> {/if} <!-- Rest props pattern --> <script> let { class: className, ...restProps } = $props(); </script> <div class="container {className}" {...restProps}> <slot /> </div> ``` ### Event Handling Patterns ```svelte <!-- Custom event callbacks via props --> <script> let { onSubmit = () => {}, onChange = () => {}, onCancel } = $props(); let value = $state(''); function handleSubmit(event) { event.preventDefault(); onSubmit(value); } function handleChange(event) { value = event.target.value; onChange(value); } </script> <form onsubmit={handleSubmit}> <input type="text" value={value} oninput={handleChange} /> <button type="submit">Submit</button> {#if onCancel} <button type="button" onclick={onCancel}>Cancel</button> {/if} </form> ``` ### Snippet Pattern (Render Props) ```svelte <!-- Parent component --> <script> import DataList from './DataList.svelte'; let items = $state([ { id: 1, name: 'Alice', role: 'Developer' }, { id: 2, name: 'Bob', role: 'Designer' } ]); </script> <DataList {items}> {#snippet itemRenderer(item)} <div class="user-card"> <h3>{item.name}</h3> <p>{item.role}</p> </div> {/snippet} </DataList> <!-- DataList.svelte --> <script> let { items, children } = $props(); </script> <ul> {#each items as item} <li> {@render children.itemRenderer(item)} </li> {/each} </ul> ``` ### Context API Pattern ```svelte <!-- ThemeProvider.svelte --> <script> import { setContext } from 'svelte'; let { children } = $props(); let theme = $state('light'); setContext('theme', { get current() { return theme; }, toggle: () => { theme = theme === 'light' ? 'dark' : 'light'; } }); </script> <div class="theme-{theme}"> {@render children()} </div> <!-- ThemeConsumer.svelte --> <script> import { getContext } from 'svelte'; const themeContext = getContext('theme'); </script> <button onclick={themeContext.toggle}> Current theme: {themeContext.current} </button> ``` ### Composition Pattern ```svelte <!-- useCounter.svelte.js --> export function useCounter(initialValue = 0) { let count = $state(initialValue); return { get value() { return count; }, increment: () => count++, decrement: () => count--, reset: () => count = initialValue }; } <!-- Component.svelte --> <script> import { useCounter } from './useCounter.svelte.js'; const counter = useCounter(10); </script> <p>Count: {counter.value}</p> <button onclick={counter.increment}>+</button> <button onclick={counter.decrement}>-</button> <button onclick={counter.reset}>Reset</button> ``` ## Common Mistakes ### Mistake 1: Not Using Runes Properly ```svelte <!-- WRONG: Mixing old and new syntax --> <script> let count = 0; // Not reactive in Svelte 5! $: doubled = count * 2; // Old syntax function increment() { count += 1; // Won't trigger reactivity } </script> <!-- CORRECT: Use runes --> <script> let count = $state(0); let doubled = $derived(count * 2); function increment() { count += 1; } </script> ``` ### Mistake 2: Mutating Props Directly ```svelte <!-- WRONG: Mutating props --> <script> let { user } = $props(); function updateName(newName) { user.name = newName; // Don't mutate props! } </script> <!-- CORRECT: Use callbacks --> <script> let { user, onUpdateUser } = $props(); function updateName(newName) { onUpdateUser({ ...user, name: newName }); } </script> ``` ### Mistake 3: Side Effects in Derived ```svelte <!-- WRONG: Side effects in $derived --> <script> let count = $state(0); let doubled = $derived(() => { console.log('Calculating doubled'); // Side effect! localStorage.setItem('count', count); // Side effect! return count * 2; }); </script> <!-- CORRECT: Use $effect for side effects --> <script> let count = $state(0); let doubled = $derived(count * 2); $effect(() => { console.log('Count changed to:', count); localStorage.setItem('count', count.toString()); }); </script> ``` ### Mistake 4: Missing Effect Cleanup ```svelte <!-- WRONG: No cleanup --> <script> let isActive = $state(false); $effect(() => { if (isActive) { const interval = setInterval(() => { console.log('tick'); }, 1000); // Missing cleanup! Memory leak! } }); </script> <!-- CORRECT: Return cleanup function --> <script> let isActive = $state(false); $effect(() => { if (!isActive) return; const interval = setInterval(() => { console.log('tick'); }, 1000); return () => clearInterval(interval); }); </script> ``` ### Mistake 5: Incorrect Reactivity with Objects ```svelte <!-- WRONG: Reassigning nested properties --> <script> let user = $state({ name: 'Alice', settings: { theme: 'light' } }); function toggleTheme() { // This works but creates a new object unnecessarily user = { ...user, settings: { ...user.settings, theme: 'dark' } }; } </script> <!-- CORRECT: Direct mutation with $state --> <script> let user = $state({ name: 'Alice', settings: { theme: 'light' } }); function toggleTheme() { // $state provides deep reactivity user.settings.theme = user.settings.theme === 'light' ? 'dark' : 'light'; } </script> ``` ### Mistake 6: Overusing Effects ```svelte <!-- WRONG: Using effect for derived values --> <script> let count = $state(0); let doubled = $state(0); $effect(() => { doubled = count * 2; // This should be $derived! }); </script> <!-- CORRECT: Use $derived --> <script> let count = $state(0); let doubled = $derived(count * 2); </script> ``` ### Mistake 7: Not Handling Async Properly ```svelte <!-- WRONG: Race conditions --> <script> let searchQuery = $state(''); let results = $state([]); $effect(() => { fetch(`/api/search?q=${searchQuery}`) .then(res => res.json()) .then(data => { results = data; // May set stale results! }); }); </script> <!-- CORRECT: Handle cancellation --> <script> let searchQuery = $state(''); let results = $state([]); $effect(() => { const controller = new AbortController(); fetch(`/api/search?q=${searchQuery}`, { signal: controller.signal }) .then(res => res.json()) .then(data => results = data) .catch(err => { if (err.name !== 'AbortError') console.error(err); }); return () => controller.abort(); }); </script> ``` ## Best Practices ### Practice 1: Component Organization ```svelte <script> // 1. Imports import { getContext } from 'svelte'; import ChildComponent from './ChildComponent.svelte'; // 2. Props let { title, items = [], onItemClick } = $props(); // 3. Context const theme = getContext('theme'); // 4. State let selectedIndex = $state(0); let isExpanded = $state(false); // 5. Derived values let selectedItem = $derived(items[selectedIndex]); let itemCount = $derived(items.length); // 6. Effects $effect(() => { console.log('Selected item changed:', selectedItem); }); // 7. Functions function handleItemClick(index) { selectedIndex = index; onItemClick?.(items[index]); } function toggleExpanded() { isExpanded = !isExpanded; } </script> <!-- 8. Template --> <div class="component"> <!-- content --> </div> <!-- 9. Styles --> <style> .component { /* styles */ } </style> ``` ### Practice 2: Type Safety with TypeScript ```svelte <script lang="ts"> interface User { id: number; name: string; email: string; } let { users, onUserSelect }: { users: User[];
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen