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é

Au lieu d’utiliser setContext et getContext directement, vous pouvez les utiliser via createContext, qui vous fournit un contexte typé et permet de ne pas avoir à fournir de clé :

context
import { function createContext<T>(): [() => T, (context: T) => T]

Returns a [get, set] pair of functions for working with context in a type-safe way.

get will throw an error if no parent component called set.

@since5.40.0
createContext
} from 'svelte';
export const [const getUserContext: () => UsergetUserContext, const setUserContext: (context: User) => UsersetUserContext] = createContext<User>(): [() => User, (context: User) => User]

Returns a [get, set] pair of functions for working with context in a type-safe way.

get will throw an error if no parent component called set.

@since5.40.0
createContext
<User>();

Lorsque vous écrivez des tests de composants, il peut être utile de créer un composant “d'emballage” qui définit le contexte afin de vérifier le comportement d’un composant consommant ce contexte. À partir de la version 5.49, vous pouvez faire ce genre de choses :

import { function mount<Props extends Record<string, any>, Exports extends Record<string, any>>(component: ComponentType<SvelteComponent<Props>> | Component<Props, Exports, any>, options: MountOptions<Props>): Exports

Mounts a component to the given target and returns the exports and potentially the props (if compiled with accessors: true) of the component. Transitions will play during the initial render unless the intro option is set to false.

mount
,
function unmount(component: Record<string, any>, options?: {
    outro?: boolean;
} | undefined): Promise<void>

Unmounts a component that was previously mounted using mount or hydrate.

Since 5.13.0, if options.outro is true, transitions will play before the component is removed from the DOM.

Returns a Promise that resolves after transitions have completed if options.outro is true, or immediately otherwise (prior to 5.13.0, returns void).

import { mount, unmount } from 'svelte';
import App from './App.svelte';

const app = mount(App, { target: document.body });

// later...
unmount(app, { outro: true });
unmount
} from 'svelte';
import { const expect: ExpectStaticexpect, const test: TestAPI

Defines a test case with a given name and test function. The test function can optionally be configured with test options.

@paramname - The name of the test or a function that will be used as a test name.
@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.
@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.
@throwsError If called inside another test function.
@examplets // Define a simple test test('should add two numbers', () => { expect(add(1, 2)).toBe(3); });
@examplets // Define a test with options test('should subtract two numbers', { retry: 3 }, () => { expect(subtract(5, 2)).toBe(3); });
test
} from 'vitest';
import { import setUserContextsetUserContext } from './context'; import
type MyComponent = SvelteComponent<Record<string, any>, any, any>
const MyComponent: LegacyComponentType
MyComponent
from './MyComponent.svelte';
test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number | TestCollectorOptions): void (+2 overloads)

Defines a test case with a given name and test function. The test function can optionally be configured with test options.

@paramname - The name of the test or a function that will be used as a test name.
@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.
@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.
@throwsError If called inside another test function.
@examplets // Define a simple test test('should add two numbers', () => { expect(add(1, 2)).toBe(3); });
@examplets // Define a test with options test('should subtract two numbers', { retry: 3 }, () => { expect(subtract(5, 2)).toBe(3); });
test
('MyComponent', () => {
function
function (local function) Wrapper(...args: any[]): {
    $on?(type: string, callback: (e: any) => void): () => void;
    $set?(props: Partial<Record<string, any>>): void;
} & Record<string, any>
Wrapper
(...args: any[]args) {
import setUserContextsetUserContext({ name: stringname: 'Bob' }); return function MyComponent(internals: Brand<"ComponentInternals">, props: Record<string, any>): ReturnType<Component<Record<string, any>, Record<string, any>>>MyComponent(...args: any[]args); } const
const component: {
    $on?(type: string, callback: (e: any) => void): () => void;
    $set?(props: Partial<Record<string, any>>): void;
} & Record<string, any>
component
=
mount<Record<string, any>, {
    $on?(type: string, callback: (e: any) => void): () => void;
    $set?(props: Partial<Record<string, any>>): void;
} & Record<...>>(component: ComponentType<...> | Component<...>, options: MountOptions<...>): {
    $on?(type: string, callback: (e: any) => void): () => void;
    $set?(props: Partial<Record<string, any>>): void;
} & Record<...>

Mounts a component to the given target and returns the exports and potentially the props (if compiled with accessors: true) of the component. Transitions will play during the initial render unless the intro option is set to false.

mount
(
function (local function) Wrapper(...args: any[]): {
    $on?(type: string, callback: (e: any) => void): () => void;
    $set?(props: Partial<Record<string, any>>): void;
} & Record<string, any>
Wrapper
, {
target: Document | Element | ShadowRoot

Target element where the component will be mounted.

target
: var document: Documentdocument.Document.body: HTMLElement

Specifies the beginning and end of the document body.

MDN Reference

body
}); expect<string>(actual: string, message?: string): Assertion<string> (+1 overload)expect(var document: Documentdocument.Document.body: HTMLElement

Specifies the beginning and end of the document body.

MDN Reference

body
.Element.innerHTML: stringinnerHTML).JestAssertion<string>.toBe: <string>(expected: string) => void

Checks that a value is what you expect. It calls Object.is to compare values. Don’t use toBe with floating-point numbers.

@exampleexpect(result).toBe(42); expect(status).toBe(true);
toBe
('<h1>Bonjour Bob !</h1>');
function unmount(component: Record<string, any>, options?: {
    outro?: boolean;
} | undefined): Promise<void>

Unmounts a component that was previously mounted using mount or hydrate.

Since 5.13.0, if options.outro is true, transitions will play before the component is removed from the DOM.

Returns a Promise that resolves after transitions have completed if options.outro is true, or immediately otherwise (prior to 5.13.0, returns void).

import { mount, unmount } from 'svelte';
import App from './App.svelte';

const app = mount(App, { target: document.body });

// later...
unmount(app, { outro: true });
unmount
(
const component: {
    $on?(type: string, callback: (e: any) => void): () => void;
    $set?(props: Partial<Record<string, any>>): void;
} & Record<string, any>
component
);
});

Cette approche fonctionne également avec hydrate et render.

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);
@see{@link https://svelte.dev/docs/svelte/$state Documentation}
@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 './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

précédent suivant