Le hook useState - Un guide complet

Le hook useState – Un guide complet

Nœud source: 1780723

Qu'est-ce qu'un état ?

Avant de plonger profondément dans le crochet useState, comprenons d'abord le terme Etat.

L'état représente des informations sur quelque chose à un moment donné.

Par exemple, considérons une zone de texte.

Initialement, il n'y a rien à l'intérieur de cette zone de texte, donc son état est vide. Supposons que vous commenciez à taper Hello à l'intérieur, pour chaque frappe de touche, l'état de la zone de texte changera. Au début, ce sera "H", puis "He", puis "Hel" et ainsi de suite jusqu'à ce qu'il devienne "Hello".

Notez également que lorsque vous tapez, vous ne perdez pas la valeur précédente. Si vous appuyez sur « H » suivi de « e », vous obtenez « He » et pas seulement « e ». En d'autres termes, vous pouvez considérer l'état comme le Mémoire de la zone de texte.

Le besoin d'état dans un composant React.

Comprenons cela à l'aide d'un exemple.

Codesanbox sans état

Ici, nous avons un Compteur de clics composant qui affiche le nombre de fois où le bouton Incrémenter a été cliqué.

Nous utilisons un variable locale "compteur" pour comptabiliser les clics.

Chaque fois que nous cliquons sur le bouton Incrémenter, poignéeCliquez fonction sera invoquée. Cette fonction augmentera la valeur du compteur de 1 et enregistrera également la valeur dans la console.

Allez-y, cliquez sur le bouton Incrémenter dans l'aperçu CodeSandbox.

Rien ne s'est passé?

Eh bien, notre logique semble être correcte. La valeur enregistrée dans la console (CodeSandbox) se met à jour correctement à chaque clic, mais pourquoi cette mise à jour n'est-elle pas reflétée dans l'interface utilisateur ?

C'est à cause du fonctionnement de React.

  • Les modifications apportées aux variables locales ne déclenchent pas de nouveau rendu.
  • Lors d'un nouveau rendu, un composant est créé à partir de zéro, c'est-à-dire que la fonction d'un composant (dans cet exemple, il s'agit de la fonction ClickCounter) est exécutée une fois de plus. Étant donné que les variables (par exemple, compteur) sont locales à la fonction, leurs valeurs précédentes sont perdues.

Alors, comment faire en sorte que le composant se souvienne des valeurs entre les rendus ?

Gif arrive à une réponse

Oui, c'est bien cela! Nous le faisons avec l'aide du utiliserÉtat crochet.

Le crochet useState

Le crochet useState fournit des mécanismes pour préserver l'état et déclencher un nouveau rendu.

Voyons son utilisation.

import React, { useState } from "react";
const state = useState(initialValue); // OR const state = React.useState(initialValue);

Le hook useState renvoie un tableau qui contient deux éléments :

  • A état variable qui conserve ses valeurs lors des re-rendus. La valeur initiale transmise à useState est affectée à la variable d'état lors du premier rendu.
  • A fonction de poseur qui met à jour la variable d'état et déclenche également un nouveau rendu.
const state = useState(0);
const data = state[0];
const setData = state[1];

En utilisant déstructuration de tableau , nous pouvons refactoriser les déclarations ci-dessus en une seule déclaration, comme indiqué ci-dessous :

const [data, setData] = useState(0);

La valeur initiale passée à useState est utilisée uniquement lors du premier rendu. Pour les re-rendus, il est ignoré.

Compteur avec useState

Maintenant, mettons à jour l'exemple de compteur précédent pour inclure le crochet useState.

  • Puisque nous avons besoin de la valeur du compteur entre les rendus, convertissons-la en un état.
const [counter, setCounter] = useState(0);
  • Appel de setCounter dans la fonction handleClick.
const handleClick = () => { setCounter(counter + 1); console.log(`%c Counter:${counter}`, "color:green");
};

La fonction setCounter mettra à jour la valeur du compteur de 1 et déclenchera un nouveau rendu. Lorsque la fonction du composant est appelée lors du nouveau rendu, la variable d'état renvoyée par useState aura la valeur mise à jour.

Essayez le CodeSandbox avec le code mis à jour. Cliquez sur le bouton Incrémenter et voyez la magie de useState en action.

Codesanbox avec useState

Vous pouvez vérifier que sur un nouveau rendu, le composant fonctionnel Compteur de clics est appelé à nouveau en consultant les journaux de la console. Le journal "ClickCounter start" qui est ajouté au début du composant sera enregistré à chaque rendu.

premier rendu

re-rendre

Fonction de mise à jour

Supposons que nous voulions augmenter la valeur du compteur de 4 à chaque clic.

const handleClick = () => { setCounter(counter + 1); setCounter(counter + 1); setCounter(counter + 1); setCounter(counter + 1); console.log(`%c Counter:${counter}`, "color:green"); };

Supposons que la valeur initiale de compteur soit 0. Qu'attendez-vous de voir une fois le bouton cliqué ?

Sans fonction de mise à jour

Vous vous attendiez à ce que le compte soit 4, n'est-ce pas ? Mais pourquoi voyez-vous 1 à la place ?

a) Chaque rendu est associé à un état. La valeur de cet état reste verrouillée pendant toute la durée de vie de ce rendu.

Notez que le journal à l'intérieur de la fonction handleClick imprime la valeur du compteur sous la forme 0.

Peu importe le nombre de fois que vous appelez la méthode setCounter, la valeur de counter reste la même.

const handleClick = () => { setCounter(counter + 1); setCounter(counter + 1); setCounter(counter + 1); setCounter(counter + 1); console.log(`%c Counter:${counter}`, "color:green"); };
b) Jusqu'à ce que tout le code à l'intérieur d'un gestionnaire d'événements soit exécuté, React ne déclenchera pas de nouveau rendu.

Pour cette raison, chaque appel setCounter ne déclenche pas un rendu individuel. Au lieu de cela, React ajoute ces fonctions de définition dans une file d'attente. Les exécute dans l'ordre dans lequel ils ont été mis en file d'attente. Les mises à jour apportées à l'état après l'exécution de toutes les instructions sont reflétées dans le rendu suivant. Cette mise en file d'attente de plusieurs mises à jour d'état est connue sous le nom de mise en lot. Cela permet à React d'être plus performant.

Par conséquent, nous obtenons ici un seul rendu au lieu de 4 rendus différents.

Cet exemple est simple et vous pouvez résoudre ce problème en mettant à jour le code comme indiqué ci-dessous :

const handleClick = () => {
setCounter(counter + 4); console.log(`%c Counter:${counter}`, "color:green"); };

Mais que se passe-t-il si vous avez un cas d'utilisation où vous souhaitez mettre à jour l'état plusieurs fois avant le prochain rendu.

C'est là que le _ mise à jour _ la fonction est pratique.

Nous pouvons refactoriser l'exemple précédent avec la fonction updater comme suit :

const handleClick = () => { setCounter(prevCounter => prevCounter + 1); setCounter(prevCounter => prevCounter + 1); setCounter(prevCounter => prevCounter + 1); setCounter(prevCounter => prevCounter + 1); console.log(`%c Counter:${counter}`, "color:green"); };

Ici compteurpréc ⇒ compteurpréc + 1 représente la fonction de mise à jour.

Comme expliqué précédemment, ces instructions de mise à jour sont également mises en file d'attente (mise en lot).

La fonction de mise à jour reçoit un état en attente/précédent qu'elle utilise pour calculer l'état suivant.

Mise en lot de la fonction de mise à jour

Ci-dessous se trouve le CodeSandbox avec la fonction de mise à jour ajoutée. Essayez de cliquer sur le bouton d'incrémentation.

Bac à sable de la fonction de mise à jour

Fonction d'initialisation

Jetez un oeil à l'exemple ci-dessous. Ici, nous appelons la fonction getItems pour obtenir la valeur initiale de l'état.

import React from "react";
import { useState } from "react";
function ListItems() { const getItems = () => { console.log(`%c getItems called`, "color:hotpink"); return Array(50).fill(0); }; const [items, setItems] = useState(getItems()); return ( <div className="card"> <ul> {items.map((item, index) => ( <li key={index}>Item {index + 1} </li>))} </ul> <button onClick={() => setItems([...items, 0])}>Add Item</button> </div> );
} export default ListItems;

Cette fonction crée un tableau de taille 50 et remplit le tableau de zéros. Reportez-vous à l'image ci-dessous.

Tableau rempli de 50 zéros

Ces éléments sont ensuite affichés à l'écran.

Tout semble aller bien mais nous avons un problème ici.

Cliquez sur le Ajouter un item (situé après la liste des éléments) pour ajouter un nouvel élément à la liste. Observez les journaux.

Sans fonction d'initialisation

Voyez-vous le problème ici?

Le journal "getItems called" est ajouté à la console chaque fois que vous ajoutez un élément. Cela signifie que cette fonction est appelée à chaque rendu.

N'oubliez pas que useState ignore la valeur initiale qui lui est transmise après le premier rendu, mais ici, la valeur initiale est toujours recalculée. Cela peut être coûteux si nous créons de grands tableaux ou effectuons des calculs lourds.

Nous pouvons résoudre ce problème en passant obtenir des éléments en tant que _ initialiseur _ fonction.

Maintenant, apportons une petite modification au code.

const [items, setItems] = useState(getItems);

Avec fonction d'initialisation

Voir la fenêtre de la console dans CodeSandbox. Notez que le journal "getItems called" n'est imprimé que sur le premier rendu. Lorsque les éléments suivants sont ajoutés, ce journal n'est pas là.

Bien qu'il n'y ait pas de différence visuelle entre les deux exemples, en termes de performances, ils sont différents.

N'oubliez pas que lorsque vous avez besoin d'une fonction pour l'état initial, passez toujours la fonction ou appelez la fonction à l'intérieur d'une autre fonction. N'appelez jamais la fonction directement.

✅ const [items, setItems] = useState(getItems);
✅ const [items, setItems] = useState(() => getItems());
❌ const [items, setItems] = useState(getItems());

Combien de hooks useState puis-je avoir

Vous pouvez avoir autant de crochets useState à l'intérieur d'un composant que nécessaire.

Voir le CodeSandbox

Crochets useState multiples

Le composant ci-dessous a trois états différents - nom d'utilisateur, mot de passe, keepMeSignedIn.

Essayez de mettre à jour les valeurs de username, keepMeSignedIn. Les états mis à jour sont enregistrés dans la console lorsque le bouton de connexion est cliqué.

Avantages

  • useState fournit un mécanisme pour déclencher un nouveau rendu et conserver l'état entre les nouveaux rendus.
  • Utilisez la fonction de mise à jour lorsque vous devez :
    • Calculez l'état suivant en fonction de l'état précédent.
    • Effectuez plusieurs mises à jour de l'état avant le prochain rendu.
  • Si l'état initial est obtenu à partir d'une fonction, utilisez la syntaxe de la fonction d'initialisation.
  • Il peut y avoir plusieurs crochets useState à l'intérieur d'un composant.

Vous avez aimé ce post ? Partagez-le avec d'autres.
Écrit à l'origine pour mon blog personnel - https://gauravsen.com/use-state-hook

Horodatage:

Plus de Fait de codeur ou de réaction