Gestion des états inter-composants dans Svelte

Comment travailler avec Props, l'API de contexte et les magasins dans Svelte pour transmettre l'état aux composants croisés de votre application

Svelte facilite la gestion de l'état d'un seul composant.

Mais comment transmettre l'état à travers les composants?

Passer de l'état à l'aide d'accessoires

La première stratégie est commune à d'autres frameworks d'interface utilisateur et elle transmet l'état à l'aide d'accessoires,lever l'état.

Lorsqu'un composant doit partager des données avec un autre, l'état peut être déplacé vers le haut dans l'arborescence des composants jusqu'à ce qu'il y ait un parent commun à ces composants.

L'état doit être transmis jusqu'à ce qu'il atteigne tous les composants qui ont besoin de ces informations d'état.

Ceci est fait en utilisantaccessoires, et c'est une technique que je pense être la meilleure car elle est simple.

Vérifier laTutoriel Svelte Propspour en savoir plus sur les accessoires.

L'API de contexte

Il y a des cas où les accessoires ne sont pas pratiques. Peut-être que 2 composants sont si éloignés dans l'arborescence des composants que nous devrions déplacer l'état vers le composant de niveau supérieur.

Dans ce cas, une autre technique peut être utilisée et elle s'appelleAPI de contexte, et c'est idéal lorsque vous souhaitez laisser plusieurs composants communiquer avec des descendants, mais que vous ne voulez pas passer d'accessoires.

L'API de contexte est fournie par 2 fonctions qui sont fournies par lesveltepaquet:getContextetsetContext.

Vous définissez un objet dans le contexte, en l'associant à une clé:

<script>
import { setContext } from 'svelte'

const someObject = {}

setContext(‘someKey’, someObject) </script>

Dans un autre composant, vous pouvez utiliser getContext pour récupérer l'objet affecté à une clé:

<script>
import { getContext } from 'svelte'

const someObject = getContext(‘someKey’) </script>

Vous ne pouvez utiliser quegetContextpour récupérer une clé soit dans le composant qui a utilisésetContext, ou dans un si ses descendants.

Si vous souhaitez faire communiquer deux composants vivant dans 2 arborescences de composants différentes, il existe un autre outil pour nous:magasins.

Utilisation des magasins Svelte

Les magasins Svelte sont un excellent outil pour gérer l'état de votre application lorsque les composants doivent se parler sans trop passer d'accessoires.

Vous devez d'abord importerwritabledesvelte/store:

import { writable } from 'svelte/store'

et créez une variable de magasin en utilisant lewritable()function, en passant la valeur par défaut comme premier argument:

const username = writable('Guest')

Cela peut être placé dans un fichier séparé, que vous pouvez importer dans plusieurs composants, par exemple appeléstore.js(ce n'est pas un composant, donc il peut être dans un.jsfichier au lieu de.svelte:

import { writable } from 'svelte/store'
export const username = writable('Guest')

Tout autre composant chargeant maintenant ce fichier peut accéder au magasin:

<script>
import { username } from './store.js'
</script>

Maintenant, la valeur de cette variable peut être définie sur une nouvelle valeur en utilisantset(), en passant la nouvelle valeur comme premier argument:

username.set('new username')

Et il peut être mis à jour en utilisant leupdate()fonction, qui diffère deset()parce que vous ne lui passez pas simplement la nouvelle valeur - vous exécutez une fonction de rappel qui reçoit la valeur actuelle comme argument:

const newUsername = 'new username!'
username.update(existing => newUsername)

Vous pouvez ajouter plus de logique ici:

username.update(existing => {
  console.log(`Updating username from ${existing} to ${newUsername}`)
  return newUsername
})

Pour obtenir la valeur de la variable storeune fois, vous pouvez utiliser leget()fonction exportée parsvelte/store:

import { readable, get } from 'svelte/store'
export const username = writable('Guest')
get(username) //'Guest'

Pour créer une variable réactive à la place, qui est mise à jour chaque fois qu'elle change, vous pouvez ajouter la variable de magasin en préfixe à l'aide de$, dans cet exemple$username. En utilisant cela, le composant sera rendu à chaque fois que la valeur stockée change.

Svelte considère$être une valeur réservée et vous empêchera de l'utiliser pour des choses qui ne sont pas liées aux valeurs des magasins (et qui pourraient prêter à confusion), donc si vous êtes habitué à ajouter des références DOM en utilisant$, ne le faites pas à Svelte.

Une autre option, la mieux adaptée si vous avez besoin d'exécuter une logique lorsque la variable change, consiste à utiliser lesubscribe()méthode deusername:

username.subscribe(newValue => {
	console.log(newValue)
})

En plus des magasins inscriptibles, Svelte propose 2 types spéciaux de magasins:magasins lisiblesetmagasins dérivés.

Magasins lisibles Svelte

Les magasins lisibles sont spéciaux car ils ne peuvent pas être mis à jour de l'extérieur - il n'y a passet()ouupdate()méthode. Au lieu de cela, une fois que vous avez défini l'état initial, ils ne peuvent pas être modifiés de l'extérieur.

La documentation officielle de Svelte montre un exemple intéressant d'utilisation d'une minuterie pour mettre à jour une date. Je peux penser à configurer une minuterie pour récupérer les ressources du réseau, effectuer un appel API, obtenir des données du système de fichiers (en utilisant un serveur Node.js local) ou tout autre élément pouvant être configuré de manière autonome.

Dans ce cas, au lieu d'utiliserwritable()pour initialiser la variable store, nous utilisonsreadable():

import { readable } from 'svelte/store'
export const count = readable(0)

Vous pouvez fournir une fonction après la valeur par défaut, qui sera responsable de sa mise à jour. Cette fonction reçoit lesetfonction pour modifier la valeur:

<script>
import { readable } from 'svelte/store'
export const count = readable(0, set => {
  setTimeout(() => {
    set(1)
  }, 1000)
})
</script>

Dans ce cas, nous mettons à jour la valeur de 0 à 1 après 1 seconde.

Vous pouvez également configurer un intervalle dans cette fonction:

import { readable, get } from 'svelte/store'
export const count = readable(0, set => {
  setInterval(() => {
	  set(get(count) + 1)
  }, 1000)
})

Vous pouvez l'utiliser dans un autre composant comme celui-ci:

<script>
import { count } from './store.js'
</script>

{$count}

Magasins dérivés de Svelte

Un magasin dérivé vous permet de créer une nouvelle valeur de magasin qui dépend de la valeur d'un magasin existant.

Vous pouvez le faire en utilisant lederived()fonction exportée parsvelte/store, qui prend comme premier paramètre la valeur de stockage existante, et comme second paramètre une fonction, qui reçoit cette valeur de stockage comme premier paramètre:

import { writable, derived } from 'svelte/store'

export const username = writable(‘Guest’)

export const welcomeMessage = derived(username, $username => { return Welcome </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">$username</span><span style="color:#e6db74">}</span><span style="color:#e6db74"> })

<script>
import { username, welcomeMessage } from ‘./store.js’
</script>

{$username} {$welcomeMessage}

Téléchargez mon gratuitManuel de Svelte


Plus de tutoriels sveltes: