useState est le hook qui permet à un composant de se souvenir de quelque chose d'un rendu à l'autre : un compteur, le texte d'un champ, l'ouverture d'un menu. Chaque fois que vous appelez son setter, React refait le rendu du composant avec la nouvelle valeur.
Cliquez sur le bouton, puis remplacez useState(0) par useState(10) dans l'éditeur. L'aperçu se reconstruit et le compteur démarre à 10.
La syntaxe
const [value, setValue] = useState(initialValue);
initialValuen'est utilisée qu'au premier rendu. À chaque rendu suivant, React l'ignore et renvoie la valeur qu'il a stockée.valueest la valeur actuelle pour ce rendu.setValueremplace la valeur et planifie un nouveau rendu.
Les noms sont à vous. useState renvoie un tableau de deux éléments et les crochets le décomposent, donc [isOpen, setIsOpen] et [email, setEmail] suivent le même pattern.
Appelez useState au niveau supérieur de votre composant, jamais dans une boucle, une condition ou une fonction imbriquée. React associe chaque appel à sa valeur stockée selon l'ordre des appels, cet ordre doit donc être le même à chaque rendu (voir les règles des hooks).
Plusieurs éléments d'état
Un composant peut appeler useState autant de fois que nécessaire. Chaque appel est une valeur indépendante.
L'état est un instantané
Le setter ne modifie pas la variable que vous avez entre les mains. Il indique à React ce que la valeur doit être au prochain rendu. Tant que ce rendu n'a pas eu lieu, le rendu actuel continue de voir l'ancienne valeur.
Ouvrez la console sous l'aperçu et cliquez une fois. Le gestionnaire affiche 0, l'ancienne valeur, puis le composant signale un nouveau rendu avec 1. Rien d'anormal : count est une constante pendant tout le rendu, et le rendu suivant en reçoit une nouvelle.
Fonctions de mise à jour
À cause de l'instantané, appeler trois fois le setter avec count + 1 ajoute un, pas trois : chaque appel calcule 0 + 1. Passez plutôt une fonction et React donne à chaque appel le résultat du précédent.
Utilisez la forme fonction de mise à jour chaque fois que la valeur suivante dépend de la précédente et que la mise à jour risque de ne pas partir directement du dernier rendu : plusieurs modifications dans un même gestionnaire, un callback de setInterval ou un effet.
Objets et tableaux dans l'état
React décide s'il faut refaire un rendu en comparant l'ancienne et la nouvelle valeur avec Object.is. Si vous modifiez un objet sur place et repassez le même objet, la comparaison conclut que rien n'a changé et l'écran reste tel quel. Passez toujours un nouvel objet ou un nouveau tableau.
{ ...user, age: user.age + 1 } copie chaque champ et en remplace un. [...tags, 'code'] ajoute un élément, et filter en retire un, les deux renvoyant un nouveau tableau. La page sur la mise à jour des tableaux et des objets traite des objets imbriqués, de la modification d'un élément dans une liste et de l'insertion au milieu.
État initial paresseux
L'argument de useState est évalué à chaque rendu, même si React ne l'utilise que la première fois. Quand le calculer coûte cher (lire localStorage, analyser une grosse chaîne), passez une fonction. React l'appelle une seule fois, au premier rendu.
// Runs readSavedNotes() on every render, then throws the result away
const [notes, setNotes] = useState(readSavedNotes());
// Runs it once
const [notes, setNotes] = useState(readSavedNotes);
const [notes, setNotes] = useState(() => readSavedNotes());
Réinitialiser l'état avec une key
L'état appartient à la position d'un composant dans l'arbre. Si vous affichez une key différente au même endroit, React le traite comme un nouveau composant et son état repart de zéro. C'est la façon la plus propre de réinitialiser un formulaire quand ce qu'il modifie change.
Tapez un message, puis changez de destinataire : le brouillon se vide. Supprimez key={to} et réessayez : le texte reste, car React voit maintenant le même Draft au même endroit.
Erreurs courantes
Afficher l'état juste après l'avoir modifié. Vous voyez l'ancienne valeur, comme montré plus haut. Affichez-le dans le corps du composant, ou calculez d'abord la valeur suivante dans une variable et utilisez-la.
Muter l'état. user.age++; setUser(user) passe le même objet, donc aucun rendu n'a lieu. Copiez d'abord.
Appeler le setter pendant le rendu. <button onClick={setCount(count + 1)}> appelle setCount pendant le rendu, ce qui déclenche un nouveau rendu, qui l'appelle à nouveau. React arrête cette boucle avec "Too many re-renders". Passez une fonction : onClick={() => setCount(count + 1)}.
Stocker des valeurs que vous pouvez calculer. Si fullName vaut toujours first + ' ' + last, calculez-le pendant le rendu au lieu de garder un troisième élément d'état qui peut se désynchroniser.
Questions fréquentes
Que renvoie useState ?
Un tableau d'exactement deux éléments : la valeur actuelle et une fonction qui la remplace. Vous les nommez vous-même par déstructuration de tableau, par convention [thing, setThing].
Pourquoi mon état ne se met-il pas à jour immédiatement ?
Appeler le setter ne modifie pas la variable que vous avez déjà. Il demande à React de refaire le rendu du composant, et la nouvelle valeur apparaît dans ce rendu suivant. Dans le gestionnaire d'événement en cours, l'ancienne valeur est toujours là, donc console.log(count) juste après setCount(count + 1) affiche l'ancien nombre.
Quand faut-il passer une fonction au setter ?
Quand la nouvelle valeur dépend de l'ancienne et que vous la modifiez plusieurs fois, ou depuis un minuteur ou un effet. setCount(c => c + 1) part toujours de la dernière valeur, alors que setCount(count + 1) part de la valeur vue par ce rendu.
useState peut-il contenir un objet ou un tableau ?
Oui, mais traitez-le comme en lecture seule. Construisez un nouvel objet ou un nouveau tableau et passez-le au setter (setUser({ ...user, name }), setItems([...items, item])). Modifier l'existant sur place ne déclenche pas de rendu.
Quelle est la différence entre useState et useReducer ?
Les deux stockent de l'état. useState convient à quelques valeurs indépendantes. useReducer déplace la logique de mise à jour dans une seule fonction qui reçoit une action, ce qui se lit mieux quand de nombreux événements modifient le même état de façons liées.