L'état comme instantané
Les variables d'état peuvent sembler être des variables JavaScript ordinaires que vous pouvez lire et écrire. Cependant, l'état se comporte davantage comme un instantané. Le modifier ne change pas la variable d'état que vous avez déjà, mais déclenche plutôt un nouveau rendu.
Vous apprendrez
- Comment la modification de l'état déclenche des nouveaux rendus
- Quand et comment l'état se met à jour
- Pourquoi l'état ne se met pas à jour immédiatement après l'avoir modifié
- Comment les gestionnaires d'événements accèdent à un « instantané » de l'état
Modifier l'état déclenche des rendus
Vous pourriez penser que votre interface utilisateur change directement en réponse à un événement utilisateur comme un clic. Dans React, cela fonctionne un peu différemment de ce modèle mental. Sur la page précédente, vous avez vu quemodifier l'état demande un nouveau renduà React. Cela signifie que pour que l'interface réagisse à l'événement, vous devezmettre à jour l'état.
Dans cet exemple, lorsque vous appuyez sur « envoyer »,setIsSent(true)indique à React de refaire le rendu de l'interface utilisateur :
Voici ce qui se passe lorsque vous cliquez sur le bouton :
- Le gestionnaire d'événements
onSubmits'exécute. setIsSent(true)définitisSentàtrueet planifie un nouveau rendu.- React refait le rendu du composant selon la nouvelle valeur de
isSent.
Examinons de plus près la relation entre l'état et le rendu.
Le rendu capture un instantané dans le temps
« Rendu »signifie que React appelle votre composant, qui est une fonction. Le JSX que vous retournez de cette fonction est comme un instantané de l'interface utilisateur à un moment donné. Ses props, gestionnaires d'événements et variables locales ont tous été calculésen utilisant son état au moment du rendu.
Contrairement à une photographie ou à une image de film, l'« instantané » d'interface utilisateur que vous retournez est interactif. Il inclut une logique comme des gestionnaires d'événements qui spécifient ce qui se passe en réponse aux entrées. React met à jour l'écran pour correspondre à cet instantané et connecte les gestionnaires d'événements. Par conséquent, appuyer sur un bouton déclenchera le gestionnaire de clic de votre JSX.
Lorsque React refait le rendu d'un composant :
- React appelle à nouveau votre fonction.
- Votre fonction retourne un nouvel instantané JSX.
- React met ensuite à jour l'écran pour correspondre à l'instantané retourné par votre fonction.
React exécute la fonction
Calcul de l'instantané
Mise à jour de l'arbre DOM
Illustré parRachel Lee Nabors
En tant que mémoire d'un composant, l'état n'est pas comme une variable ordinaire qui disparaît après le retour de votre fonction. L'état « vit » en réalité dans React lui-même — comme sur une étagère ! — en dehors de votre fonction. Lorsque React appelle votre composant, il vous donne un instantané de l'état pour ce rendu particulier. Votre composant retourne un instantané de l'interface utilisateur avec un nouvel ensemble de props et de gestionnaires d'événements dans son JSX, tous calculésen utilisant les valeurs d'état de ce rendu !
Vous dites à React de mettre à jour l'état
React met à jour la valeur de l'état
React passe un instantané de la valeur d'état dans le composant
Illustré parRachel Lee Nabors
Voici une petite expérience pour vous montrer comment cela fonctionne. Dans cet exemple, vous pourriez vous attendre à ce que cliquer sur le bouton « +3 » incrémente le compteur trois fois car il appellesetNumber(number + 1)trois fois.
Voyez ce qui se passe lorsque vous cliquez sur le bouton « +3 » :
Remarquez quenumberne s'incrémente qu'une seule fois par clic !
Définir un état ne le modifie que pour leprochainrendu.Lors du premier rendu,numbervalait0. C'est pourquoi, dans le gestionnairede ce rendu,onClick, la valeur denumberreste0même après l'appel desetNumber(number + 1) :
Voici ce que le gestionnaire de clic de ce bouton demande à React de faire :
setNumber(number + 1):numbervaut0doncsetNumber(0 + 1).- React se prépare à changer
numberen1lors du prochain rendu.
- React se prépare à changer
setNumber(number + 1):numbervaut0doncsetNumber(0 + 1).- React se prépare à changer
numberen1lors du prochain rendu.
- React se prépare à changer
setNumber(number + 1):numbervaut0doncsetNumber(0 + 1).- React se prépare à changer
numberen1lors du prochain rendu.
- React se prépare à changer
Même si vous avez appelésetNumber(number + 1)trois fois, dans le gestionnaire d'événementde ce rendu, numbervaut toujours0, donc vous définissez l'état à1trois fois. C'est pourquoi, une fois que votre gestionnaire d'événement est terminé, React effectue un nouveau rendu du composant avecnumberégal à1plutôt qu'à3.
Vous pouvez aussi visualiser cela en remplaçant mentalement les variables d'état par leurs valeurs dans votre code. Puisque la variable d'étatnumber vaut 0pource rendu, son gestionnaire d'événement ressemble à ceci :
Pour le prochain rendu,numbervaut1, donc le gestionnaire de clicde ce renduressemble à ceci :
C'est pourquoi cliquer à nouveau sur le bouton définira le compteur à2, puis à3au clic suivant, et ainsi de suite.
État au fil du temps
C'était amusant. Essayez de deviner ce que l'alerte affichera en cliquant sur ce bouton :
Si vous utilisez la méthode de substitution vue précédemment, vous pouvez deviner que l'alerte affiche « 0 » :
Mais si vous placez un minuteur sur l'alerte, pour qu'elle ne se déclenchequ'aprèsle nouveau rendu du composant ? Afficherait-elle « 0 » ou « 5 » ? Faites une supposition !
Surpris ? Si vous utilisez la méthode de substitution, vous pouvez voir l'« instantané » de l'état passé à l'alerte.
L'état stocké dans React a peut-être changé au moment où l'alerte s'exécute, mais celle-ci a été planifiée en utilisant un instantané de l'état au moment où l'utilisateur a interagi avec lui !
La valeur d'une variable d'état ne change jamais au cours d'un rendu,même si le code de son gestionnaire d'événements est asynchrone. À l'intérieur dugestionnaire onClick de ce renduonClick, la valeur denumber reste 0même après l'appel desetNumber(number + 5). Sa valeur a été « figée » lorsque React a « pris l'instantané » de l'interface utilisateur en appelant votre composant.
Voici un exemple de la façon dont cela rend vos gestionnaires d'événements moins sujets aux erreurs de timing. Ci-dessous se trouve un formulaire qui envoie un message avec un délai de cinq secondes. Imaginez ce scénario :
- Vous appuyez sur le bouton « Envoyer », envoyant « Bonjour » à Alice.
- Avant la fin du délai de cinq secondes, vous changez la valeur du champ « À » pour « Bob ».
Que pensez-vous que l'alertva afficher ? Affichera-t-elle « Vous avez dit Bonjour à Alice » ? Ou affichera-t-elle « Vous avez dit Bonjour à Bob » ? Faites une supposition en fonction de ce que vous savez, puis essayez :
React maintient les valeurs d'état « figées » au sein des gestionnaires d'événements d'un rendu.Vous n'avez pas à vous soucier de savoir si l'état a changé pendant l'exécution du code.
Mais que faire si vous souhaitez lire l'état le plus récent avant un nouveau rendu ? Vous devrez utiliser unefonction de mise à jour d'état, abordée sur la page suivante !
Récapitulatif
- Définir un état demande un nouveau rendu.
- React stocke l'état en dehors de votre composant, comme sur une étagère.
- Lorsque vous appelez
useState, React vous donne un instantané de l'étatpour ce rendu. - Les variables et les gestionnaires d'événements ne « survivent » pas aux nouveaux rendus. Chaque rendu a ses propres gestionnaires d'événements.
- Chaque rendu (et les fonctions qu'il contient) « verra » toujours l'instantané de l'état que React a donné àcerendu.
- Vous pouvez mentalement substituer l'état dans les gestionnaires d'événements, de la même manière que vous pensez au JSX rendu.
- Les gestionnaires d'événements créés dans le passé ont les valeurs d'état du rendu dans lequel ils ont été créés.
Essayez quelques défis
Challenge 1 of 1:Implémenter un feu de circulation #
Voici un composant de feu piéton qui bascule lorsque le bouton est pressé :
Ajoutez une alert au gestionnaire de clic. Lorsque le feu est vert et affiche « Walk », cliquer sur le bouton devrait dire « Stop is next ». Lorsque le feu est rouge et affiche « Stop », cliquer sur le bouton devrait dire « Walk is next ».
Cela fait-il une différence si vous placez l'alert avant ou après l'appel à setWalk ?
