$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 sicount
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>