Skip to main content

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”). Le composant parent définit un contexte avec setContext(key, value)...

Parent
<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 :

Child
<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>

C’est particulièrement utile lorsque Parent.svelte n’a pas directement conscience de Child.svelte, mais en fait le rendu via le snippet children (demo):

<Parent>
	<Child />
</Parent>

La clé ('my-context', dans l’exemple ci-dessus) et le contexte lui-même peuvent être n’importe quelle valeur JavaScript.

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 (demo)...

<script>
	import { setContext } from 'svelte';
	import Child from './Child.svelte';

	let counter = $state({
		count: 0
	});

	setContext('counter', counter);
</script>

<button onclick={() => counter.count += 1}>
	incrémenter
</button>

<Child />
<Child />
<Child />

... 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.

Contexte typé

Une astuce utile est d’englober les appels à setContext et getContext dans des fonctions utilitaires qui vous permettent de préserver votre typage :

context
import { function getContext<T>(key: any): T

Retrieves the context that belongs to the closest parent component with the specified key. Must be called during component initialisation.

getContext
, function setContext<T>(key: any, context: T): T

Associates an arbitrary context object with the current component and the specified key and returns that object. The context is then available to children of the component (including slotted content) with getContext.

Like lifecycle functions, this must be called during component initialisation.

setContext
} from 'svelte';
let let key: {}key = {}; /** @param {User} user */ export function function setUserContext(user: User): void
@paramuser
setUserContext
(user: User
@paramuser
user
) {
setContext<User>(key: any, context: User): User

Associates an arbitrary context object with the current component and the specified key and returns that object. The context is then available to children of the component (including slotted content) with getContext.

Like lifecycle functions, this must be called during component initialisation.

setContext
(let key: {}key, user: User
@paramuser
user
);
} export function function getUserContext(): UsergetUserContext() { return /** @type {User} */ (getContext<User>(key: any): User

Retrieves the context that belongs to the closest parent component with the specified key. Must be called during component initialisation.

getContext
(let key: {}key));
}
import { function getContext<T>(key: any): T

Retrieves the context that belongs to the closest parent component with the specified key. Must be called during component initialisation.

getContext
, function setContext<T>(key: any, context: T): T

Associates an arbitrary context object with the current component and the specified key and returns that object. The context is then available to children of the component (including slotted content) with getContext.

Like lifecycle functions, this must be called during component initialisation.

setContext
} from 'svelte';
let let key: {}key = {}; export function function setUserContext(user: User): voidsetUserContext(user: Useruser: User) { setContext<User>(key: any, context: User): User

Associates an arbitrary context object with the current component and the specified key and returns that object. The context is then available to children of the component (including slotted content) with getContext.

Like lifecycle functions, this must be called during component initialisation.

setContext
(let key: {}key, user: Useruser);
} export function function getUserContext(): UsergetUserContext() { return getContext<User>(key: any): User

Retrieves the context that belongs to the closest parent component with the specified key. Must be called during component initialisation.

getContext
(let key: {}key) as User;
}

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 :

state.svelte
export const 
const myGlobalState: {
    user: {};
}
myGlobalState
=
function $state<{
    user: {};
}>(initial: {
    user: {};
}): {
    user: {};
} (+1 overload)
namespace $state

Declares reactive state.

Example:

let count = $state(0);

https://svelte.dev/docs/svelte/$state

@paraminitial The initial value
$state
({
user: {}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 !)...

App
<script>
	import { myGlobalState } from 'svelte';

	let { data } = $props();

	if (data.user) {
		myGlobalState.user = data.user;
	}
</script>
<script lang="ts">
	import { myGlobalState } from 'svelte';

	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

précédent suivant