Skip to main content

$derived

Vous pouvez déclarer un état dérivé avec la rune $derived :

<script>
	let count = $state(0);
	let doubled = $derived(count * 2);
</script>

<button onclick={() => count++}>
	{doubled}
</button>

<p>Le double de {count} vaut {doubled}</p>

L’expression à l’intérieur de $derived(...) ne doit pas contenir d’effet de bord. Svelte empêchera les changements d’état (par ex. count++) à l’intérieur d’expressions dérivées.

Comme avec $state, vous pouvez définir les champs d’une classe en utilisant $derived.

Le code d’un composant Svelte est uniquement exécuté à sa création. Sans la rune $derived, doubled maintiendrait sa valeur originale même si count change de valeur.

$derived.by

Parfois, certaines derivations complexes nécessitent plus qu’une simple expression. Dans ces cas là, vous pouvez utiliser $derived.by, qui prend une fonction comme argument.

<script>
	let numbers = $state([1, 2, 3]);
	let total = $derived.by(() => {
		let total = 0;
		for (const n of numbers) {
			total += n;
		}
		return total;
	});
</script>

<button onclick={() => numbers.push(numbers.length + 1)}>
	{numbers.join(' + ')} = {total}
</button>

Par essence, $derived(expression) est équivalent à $derived.by(() => expression).

Comprendre les dépendences

Tout ce qui est lu de manière synchrone au de l’expression de $derived (ou du corps de la fonction de $derived.by) est considérée comme une dépendence de l’état dérivé. Lorsqu’un des états dont il dépend est mis à jour, l’état dérivé sera marqué comme sale et recalculé la prochaine fois que sa valeur est lue.

Pour exempter un morceau d’état d’être considéré comme une dépendance, utilisez untrack.

Écraser des valeurs dérivées

Les expressions dérivées sont recalculées lorsque leurs dépendances changent, mais vous pouvez temporairement écraser leurs valeurs en les réassignant (à moins qu’elles ne soient déclarées avec const). Ceci peut être utile pour des choses comme des interfaces optimistes, où une valeur est dérivée de la “source de vérité” (comme des données venant de votre serveur), mais vous souhaitez montrer un feedback immédiat à l’utilisateur ou utilisatrice :

<script>
	let { post, like } = $props();

	let likes = $derived(post.likes);

	async function onclick() {
		// increment the `likes` count immediately...
		// incrémente le compte de "likes" immédiatement...
		likes += 1;

		// et prévient le serveur, qui va faire sa mise à jour et redescendre la nouvelle valeur de `post`
		try {
			await like();
		} catch {
			// échec ! annule le changement
			likes -= 1;
		}
	}
</script>

<button {onclick}>🧡 {likes}</button>

Avant Svelte 5.25, les valeurs dérivées étaient uniquement en lecture seule.

Dérivées et réactivité

À la différence de $state, qui convertit les objets et les tableaux en proxies profondément réactifs, les valeurs $derived sont laissées telles quelles. Par exemple, dans un cas comme celui-ci ...

let items = $state([...]);

let index = $state(0);
let selected = $derived(items[index]);

... vous pouvez changer (ou bind:) les propriétés de selected et cela affectera le tableau d’items sous-jacent. Si items n’était pas profondément réactif, muter selected n’aurait aucun effet.

Propagation de la mise à jour

Svelte utilise un concept appelée réactivité push-pull — lorsque l’état est mis à jour, tout ce qui dépend de l’état (directement ou non) est immédiatement notifié du changement (le ‘push’), mais les valeurs dérivées ne sont pas ré-évaluées tant qu’elles ne sont lues (le ‘pull’).

Si la nouvelle valeur d’un état dérivé est identique en termes de référence que la valeur précédente, les mises à jour en aval seront ignorées. Autrement dit, Svelte ne mettra à jour le texte au sein du bouton que lorsque large change, pas lorsque count change, même si large dépend de count :

<script>
	let count = $state(0);
	let large = $derived(count > 10);
</script>

<button onclick={() => count++}>
	{large}
</button>

Modifier cette page sur Github

précédent suivant