Kurs Svelte i SvelteKit · Moduł 4: Props i zdarzenia
Context API
W tej lekcji5
Dla głęboko zagnieżdżonych komponentów, Context API pozwala uniknąć "prop drilling".
Problem: Prop drilling
App
└── Layout
└── Sidebar
└── Navigation
└── NavItem <-- potrzebuje danych z App!Przekazywanie props przez każdy poziom jest uciążliwe.
Rozwiązanie: Context
<!-- App.svelte -->
<script>
import { setContext } from 'svelte';
import Layout from './Layout.svelte';
const user = $state({
name: 'Ragnar',
role: 'jarl',
gold: 1000
});
// Ustaw kontekst - dostępny dla wszystkich potomków
setContext('user', user);
</script>
<Layout />
<button onclick={() => user.gold += 100}>+100 złota</button><!-- NavItem.svelte (głęboko zagnieżdżony) -->
<script>
import { getContext } from 'svelte';
// Pobierz kontekst - działa na dowolnym poziomie!
const user = getContext('user');
</script>
<div class="nav-item">
<span>{user.name}</span>
<span>({user.role}, {user.gold} złota)</span>
</div>Do kontekstu trafia obiekt $state, więc potomkowie widzą jego zmiany. Zmieniaj jego pola (user.gold += 100) zamiast przypisywać nowy obiekt - inaczej potomkowie zostaną ze starym.
Typowany Context
Klucze kontekstu i funkcje do nich warto trzymać w jednym pliku. Od Svelte 5.40 robi to za Ciebie createContext - zwraca parę funkcji, bez ręcznego klucza:
// context.ts
import { createContext } from 'svelte';
interface User {
name: string;
role: string;
}
export const [getUserContext, setUserContext] = createContext<User>();W starszych wersjach Svelte 5 to samo zapiszesz przez setContext i getContext z unikalnym kluczem:
// context.js
import { getContext, setContext } from 'svelte';
const USER_KEY = Symbol('user');
export function setUserContext(user) {
setContext(USER_KEY, user);
}
export function getUserContext() {
return getContext(USER_KEY);
}<!-- App.svelte -->
<script>
import { setUserContext } from './context.js';
const user = $state({ name: 'Ragnar', role: 'jarl' });
setUserContext(user);
</script><!-- DeepChild.svelte -->
<script>
import { getUserContext } from './context.js';
const user = getUserContext();
</script>
<p>{user.name}</p>Context vs Props vs stan globalny
| Metoda | Kiedy używać |
|---|---|
| Props | Bezpośredni rodzic-dziecko |
| Context | Głęboka hierarchia, dane "per-tree" |
| Stan globalny | $state w pliku .svelte.js albo stores (moduł 8), wiele drzew komponentów |
Przykład: Theme Context
<!-- ThemeProvider.svelte -->
<script>
import { setContext } from 'svelte';
let { children } = $props();
let theme = $state('dark');
setContext('theme', {
get current() { return theme; },
toggle() { theme = theme === 'dark' ? 'light' : 'dark'; }
});
</script>
<div class="theme-{theme}">
{@render children()}
</div><!-- ThemedButton.svelte -->
<script>
import { getContext } from 'svelte';
const theme = getContext('theme');
</script>
<button class={theme.current} onclick={theme.toggle}>
Zmień motyw ({theme.current})
</button>Getter current zawsze zwraca aktualną wartość theme, więc przycisk odświeża się po każdej zmianie motywu.
Context to tajne przejścia w pałacu Asgardu - dane płyną bez przeszkód!
Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Kiedy używać Context API zamiast props?
2. Jakie funkcje z pakietu svelte ustawiają i pobierają kontekst po kluczu?
Zadania praktyczne w grze
- Klikanie w kolejności
Kiedy używać: props (bezpośrednia), context (głęboka), stan globalny (stores lub .svelte.js)