Contexte
Le contexte permet aux composants d’accéder aux valeurs appartenant aux composants parents sans les fournir en tant que props (potentiellement au travers de plusieurs couches de composants intermédiaires, ce qui s’appelle faire du “prop-drilling”).
Vous pouvez créer une triplette de fonctions [get, set, has] avec createContext , vous
permettant ainsi de définir le contexte dans un composant parent et le récupérer dans un composant
enfant :
<script>
import Parent from './Parent.svelte';
import Child from './Child.svelte';
</script>
<Parent>
<Child />
</Parent><script lang="ts">
import Parent from './Parent.svelte';
import Child from './Child.svelte';
</script>
<Parent>
<Child />
</Parent><script>
import { setUserContext } from './context';
let { children } = $props();
setUserContext({ name: 'tout le monde' });
</script>
{@render children()}<script lang="ts">
import { setUserContext } from './context';
let { children } = $props();
setUserContext({ name: 'tout le monde' });
</script>
{@render children()}<script>
import { getUserContext } from './context';
const user = getUserContext();
</script>
<h1>bonjour {user.name}, dans le composant Child.svelte</h1><script lang="ts">
import { getUserContext } from './context';
const user = getUserContext();
</script>
<h1>bonjour {user.name}, dans le composant Child.svelte</h1>import { createContext } from 'svelte';
interface User {
name: string;
}
export const [getUserContext, setUserContext] = createContext<User>();
createContexta été ajouté dans la version 5.40. Si vous utilisez une version plus ancienne de Svelte, vous devez plutôt utilisersetContextetgetContext.
Ceci est particulièrement utile lorque Parent.svelte n’est pas directement conscient de
Child.svelte, mais l’affiche en tant que partie d’un snippet children comme montré
ci-dessous.
setContext et getContext
Vous pouvez directement utiliser setContext et getContext en tant qu’alternative à getContext.
Le composant parent définit le contexte avec setContext(key, value)...
<script>
import { setContext } from 'svelte';
setContext('my-context', 'bonjour depuis Parent.svelte');
</script><script lang="ts">
import { setContext } from 'svelte';
setContext('my-context', 'bonjour depuis Parent.svelte');
</script>... et l’enfant le récupère avec getContext :
<script>
import { getContext } from 'svelte';
const message = getContext('my-context');
</script>
<h1>{message}, au sein de Child.svelte</h1><script lang="ts">
import { getContext } from 'svelte';
const message = getContext('my-context');
</script>
<h1>{message}, au sein de Child.svelte</h1>La clé ('my-context', dans l’exemple ci-dessus) et le contexte lui-même peuvent être n’importe
quelle valeur JavaScript.
createContextest recommandé car il fournit un meilleur typage et rend non nécessaire l’usage de clés.
En plus de setContext et getContext, Svelte expose les
fonctions hasContext et getAllContexts.
Utiliser le contexte avec l’état
Vous pouvez stocker des états réactifs dans le contexte...
<script>
import { setCounter } from './context.ts';
import Child from './Child.svelte';
let counter = $state({
count: 0
});
setCounter(counter);
</script>
<button onclick={() => counter.count += 1}>
incrémenter
</button>
<Child />
<Child />
<Child />
<button onclick={() => counter.count = 0}>
réinitialiser
</button><script lang="ts">
import { setCounter } from './context.ts';
import Child from './Child.svelte';
let counter = $state({
count: 0
});
setCounter(counter);
</script>
<button onclick={() => counter.count += 1}>
incrémenter
</button>
<Child />
<Child />
<Child />
<button onclick={() => counter.count = 0}>
réinitialiser
</button><script>
import { getCounter } from './context.ts';
const counter = getCounter();
</script>
<p>{counter.count}</p><script lang="ts">
import { getCounter } from './context.ts';
const counter = getCounter();
</script>
<p>{counter.count}</p>import { createContext } from 'svelte';
interface Counter {
count: number;
}
export const [getCounter, setCounter] = createContext<Counter>();... même s’il toutefois noter que si vous réassignez counter plutôt que de le mettre à jour,
vous “casserez le lien” — en d’autres termes, plutôt que ceci...
<button onclick={() => counter = { count: 0 } }>
réinitialiser
</button>... vous devez faire ceci :
<button onclick={() => counter.count = 0}>
réinitialiser
</button>Svelte vous avertira si vous vous trompez.
De même, pour passer des valeurs primitives à travers le contexte, utilisez des fonctions comme décrit dans Passer de l’état à des fonctions.
Monter des composants ayant du contexte
Pour monter un composant avec un contexte spécifique, créez un composant englobant qui va définir le
contexte avant de rendre votre composant. Ceci est notamment utile pour les tests de
composants, ou pour tout autre
scénario qui a besoin de fournir un contexte au travers de mount. Depuis la version 5.49, vous
pouvez faire ce genre de choses :
import { mount, unmount } from 'svelte';
import { expect, test } from 'vitest';
import { setUserContext } from './context';
import MyComponent from './MyComponent.svelte';
test('MyComponent', () => {
function Wrapper(...args) {
setUserContext({ name: 'Bob' });
return MyComponent(...args);
}
const component = mount(Wrapper, {
target: document.body
});
expect(document.body.innerHTML).toBe('<h1>Bonjour Bob !</h1>');
unmount(component);
});Cette approche fonctionne également avec hydrate et
render.
Le contexte défini par le composant englobant s’applique uniquement à cet arbre de composants
montés. Chaque appel à mount, hydrate ou render crée une instance englobante distincte, afin
que le contexte ne fuite pas dans d’autres composants montés.
Remplacer l’état global
Lorsque vous avez un état partagé par plusieurs composants différents, vous pourriez être tenté•e•s de le mettre dans son propre module et de simplement l’importer là où il est nécessaire :
export const myGlobalState = $state({
user: {
// ...
}
// ...
});Dans plusieurs situations ceci ne posera pas de problèmes, mais il y a un risque : si vous mutez l’état lors d’un rendu côté serveur (ce qui est découragé, mais tout à fait possible !)...
<script>
import { myGlobalState } from './state.svelte.js';
let { data } = $props();
if (data.user) {
myGlobalState.user = data.user;
}
</script><script lang="ts">
import { myGlobalState } from './state.svelte.js';
let { data } = $props();
if (data.user) {
myGlobalState.user = data.user;
}
</script>... alors les données pourraient être accessibles par la prochaine personne utilisant votre site. Le contexte résout ce problème car il n’est pas partagé entre les requêtes.
Modifier cette page sur Github llms.txt