Cours Svelte et SvelteKit · Module 4: Props et événements
Context API
Dans cette leçon5
Pour des composants profondément imbriqués, la Context API permet d'éviter le « prop drilling ».
Problème : Le Prop Drilling
App
└── Layout
└── Sidebar
└── Navigation
└── NavItem <-- a besoin des données de App !Transmettre les props à chaque niveau est fastidieux.
Solution : Context
<!-- App.svelte -->
<script>
import { setContext } from 'svelte';
import Layout from './Layout.svelte';
const user = $state({
name: 'Ragnar',
role: 'jarl',
gold: 1000
});
// Définit le context - disponible pour tous les descendants
setContext('user', user);
</script>
<Layout />
<button onclick={() => user.gold += 100}>+100 pièces d'or</button><!-- NavItem.svelte (profondément imbriqué) -->
<script>
import { getContext } from 'svelte';
// Récupère le context - fonctionne à n'importe quel niveau !
const user = getContext('user');
</script>
<div class="nav-item">
<span>{user.name}</span>
<span>({user.role}, {user.gold} pièces d'or)</span>
</div>Le context contient un objet $state, donc les descendants voient ses changements. Modifie ses champs (user.gold += 100) au lieu d'assigner un nouvel objet, sinon les descendants gardent l'ancien.
Context typé
Mieux vaut garder les clés de context et leurs fonctions dans un seul fichier. Depuis Svelte 5.40, createContext s'en charge : il renvoie une paire de fonctions, sans clé à gérer :
// context.ts
import { createContext } from 'svelte';
interface User {
name: string;
role: string;
}
export const [getUserContext, setUserContext] = createContext<User>();Dans les versions plus anciennes de Svelte 5, tu écris la même chose avec setContext et getContext et une clé unique :
// 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 état global
| Méthode | Quand l'utiliser |
|---|---|
| Props | Parent-enfant direct |
| Context | Hiérarchie profonde, données par arbre |
| État global | $state dans un fichier .svelte.js ou stores (module 8), plusieurs arbres de composants |
Exemple : Context de thème
<!-- 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}>
Changer de thème ({theme.current})
</button>Le getter current renvoie toujours la valeur actuelle de theme, donc le bouton se met à jour après chaque changement de thème.
Le Context est comme des passages secrets dans le palais d'Asgard : les données circulent sans obstacle !
Entrées de la documentation utilisées dans cette leçon
Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Quand utiliser le Context API à la place des props ?
2. Quelles fonctions du paquet svelte définissent et récupèrent un contexte par clé ?
Tâches pratiques dans le jeu
- Clique dans l'ordre
Quand utiliser : props (directe), context (profonde), état global (stores ou .svelte.js)