5. Réactivité universelle
Elle est partout
Nous sommes maintenant capables de faire évoluer l'état de nos composants. Mais uniquement au sein du composant lui-même. Les états que nous savons déclarer sont locaux au composant dans lequel ils sont déclarés. Nous ne sommes pas encore capables de faire évoluer un état de manière globale, c'est-à-dire le modifier dans un composant, mais en voir les effets dans un autre.
Pour cela, il faut comprendre que la réactivité de Svelte est universelle. Vous pouvez créer des états réactifs n'importe où : à la racine d'un composant, au sein d'une fonction dans un composant, mais aussi en dehors d'un composant. Ce qui permet plusieurs choses :
- créer plusieurs instances d'un même état dans un même composant...
- ... ou dans des composants différents
- consommer un même état dans des composants différents
Créer des états globaux avec Svelte 4 était également possible : il fallait utiliser des stores. Un des désavantages néanmoins était que déclarer un store était très différent de déclarer un état, ce qui rendait le concept dur à appréhender.
Créer plusieurs instances d'un même état
Par exemple, si nous déclarons un état de cette manière :
<script>
let count = $state(0); // déclaration
function increment() {
// mise à jour
count += 1;
}
</script>
<button onclick={increment}>
<!-- consommation -->
clicks: {count}
</button>
Nous avons ici trois choses concernant l'état : sa déclaration, sa mise à jour, et sa consommation.
Nous pouvons tout à fait écrire la même de cette manière :
<script>
// création d'une machine à créer des états de type counter
function createCounter() {
let count = $state(0); // déclaration
function increment() {
// mise à jour
count += 1;
}
return {
get count() {
return count;
},
increment
};
}
const counter = createCounter(); // création d'un état de type counter
</script>
<button onclick={counter.increment}>
<!-- consommation -->
clicks: {counter.count}
</button>
Utiliser un accesseur
get()
permet de toujours avoir accès à la valeur courante decount
.
La fonction createCounter
nous permet maintenant de créer plusieurs d'états fonctionnant de la
même façon, mais évoluant chacun indépendamment :
<script>
function createCounter() {...}
const bikes = createCounter();
const cars = createCounter();
</script>
<button onclick={bikes.increment}> bikes: {bikes.count} </button>
<button onclick={cars.increment}>
cars: {cars.count}
</button>
Modules .svelte.ts
Jusque là, nous avons uniquement défini des $state
au sein de composants Svelte, c'est-à-dire dans
des fichiers .svelte
.
Mais il est possible d'utiliser n'importe quelle rune en dehors d'un composant, dans des fichiers
.svelte.ts
(ou .svelte.js
).
// createCounter.svelte.ts
export function createCounter() {
let count = $state(0);
function increment() {
count += 1;
}
return {
get count() {
return count;
},
increment
};
}
Vous n'avez pas besoin d'importer quoi que ce soit pour utiliser une rune dans un fichier
.svelte.js
ou.svelte.ts
. Svelte se charge de les rendre disponibles.
Ainsi, nous pouvons créer des états sur un même modèle dans des composants différents.
<script>
import { createCounter } from './createCounter.svelte.ts';
const bikes = createCounter();
</script>
État global
Si vous avez besoin de suivre une même valeur à plusieurs endroits de votre application, il vous suffit de créer une instance de cet état à l'extérieur de vos composants, et de l'importer là où il est nécessaire.
// points.svelte.ts
function createCounter() { ... }
export const points = createCounter();
<!-- Board.svelte -->
<script>
import { points } from './points.svelte.ts';
</script>
<div>{points.value}</div>
<!-- Player.svelte -->
<script>
import { points } from './points.svelte.ts';
</script>
<button onclick={points.increment}> Jouer </button>