Réagir aux entrées avec l'état
React offre une manière déclarative de manipuler l'interface utilisateur. Au lieu de manipuler directement des éléments individuels de l'UI, vous décrivez les différents états dans lesquels votre composant peut se trouver, et vous basculez entre eux en réponse aux actions de l'utilisateur. Cela ressemble à la façon dont les designers conçoivent l'interface utilisateur.
Vous apprendrez
- Comment la programmation déclarative d'UI diffère de la programmation impérative d'UI
- Comment énumérer les différents états visuels possibles de votre composant
- Comment déclencher les changements entre les différents états visuels depuis le code
Comparaison entre l'UI déclarative et l'UI impérative
Lorsque vous concevez des interactions d'interface utilisateur, vous pensez probablement à la façon dont l'UIchangeen réponse aux actions de l'utilisateur. Prenons l'exemple d'un formulaire qui permet à l'utilisateur de soumettre une réponse :
- Lorsque vous tapez quelque chose dans le formulaire, le bouton "Soumettre"devient actif.
- Lorsque vous appuyez sur "Soumettre", le formulaire et le boutondeviennent désactivés,et un indicateur de chargementapparaît.
- Si la requête réseau réussit, le formulaireest masqué,et le message "Merci"apparaît.
- Si la requête réseau échoue, un message d'erreurapparaît,et le formulaireredevient actif.
Enprogrammation impérative,ce qui précède correspond directement à la façon dont vous implémentez l'interaction. Vous devez écrire les instructions exactes pour manipuler l'UI en fonction de ce qui vient de se passer. Voici une autre façon d'y penser : imaginez être assis à côté de quelqu'un dans une voiture et lui indiquer tour par tour où aller.

Illustré parRachel Lee Nabors
Ils ne savent pas où vous voulez aller, ils suivent simplement vos commandes. (Et si vous vous trompez dans les directions, vous finissez au mauvais endroit !) C'est appeléimpératifparce que vous devez "commander" chaque élément, de l'indicateur de chargement au bouton, en disant à l'ordinateurcommentmettre à jour l'UI.
Dans cet exemple de programmation impérative d'UI, le formulaire est construitsansReact. Il utilise uniquement leDOMdu navigateur :
Manipuler l'UI de manière impérative fonctionne assez bien pour des exemples isolés, mais cela devient exponentiellement plus difficile à gérer dans des systèmes plus complexes. Imaginez mettre à jour une page remplie de différents formulaires comme celui-ci. Ajouter un nouvel élément d'UI ou une nouvelle interaction nécessiterait de vérifier soigneusement tout le code existant pour s'assurer de ne pas introduire de bug (par exemple, oublier d'afficher ou de masquer quelque chose).
React a été créé pour résoudre ce problème.
Dans React, vous ne manipulez pas directement l'UI—c'est-à-dire que vous n'activez, ne désactivez, n'affichez ou ne masquez pas directement les composants. Au lieu de cela, vousdéclarez ce que vous voulez afficher,et React détermine comment mettre à jour l'UI. Pensez à monter dans un taxi et dire au chauffeur où vous voulez aller au lieu de lui indiquer exactement où tourner. C'est le travail du chauffeur de vous y amener, et il pourrait même connaître des raccourcis auxquels vous n'avez pas pensé !

Illustré parRachel Lee Nabors
Penser l'UI de manière déclarative
Vous avez vu comment implémenter un formulaire de manière impérative ci-dessus. Pour mieux comprendre comment penser en React, vous allez parcourir la réimplémentation de cette UI dans React ci-dessous :
- Identifiezles différents états visuels de votre composant
- Déterminezce qui déclenche ces changements d'état
- Représentezl'état en mémoire en utilisant
useState - Supprimeztoutes les variables d'état non essentielles
- Connectezles gestionnaires d'événements pour définir l'état
Étape 1 : Identifiez les différents états visuels de votre composant
En informatique, vous avez peut-être entendu parler d'une« machine à états »qui se trouve dans l'un de plusieurs « états ». Si vous travaillez avec un designer, vous avez peut-être vu des maquettes pour différents « états visuels ». React se situe à l'intersection du design et de l'informatique, donc ces deux idées sont des sources d'inspiration.
Tout d'abord, vous devez visualiser tous les différents « états » de l'interface utilisateur que l'utilisateur pourrait voir :
- Vide: Le formulaire a un bouton « Soumettre » désactivé.
- Saisie: Le formulaire a un bouton « Soumettre » activé.
- Envoi: Le formulaire est complètement désactivé. Un indicateur de chargement est affiché.
- Succès: Un message « Merci » est affiché à la place du formulaire.
- Erreur: Identique à l'état Saisie, mais avec un message d'erreur supplémentaire.
Tout comme un designer, vous voudrez « maquetter » ou créer des « maquettes » pour les différents états avant d'ajouter la logique. Par exemple, voici une maquette pour la partie visuelle du formulaire uniquement. Cette maquette est contrôlée par une prop appeléestatusavec une valeur par défaut de'empty':
Vous pouvez nommer cette prop comme vous le souhaitez, le nom n'est pas important. Essayez de modifierstatus = 'empty'enstatus = 'success'pour voir le message de succès apparaître. La maquettage vous permet d'itérer rapidement sur l'interface utilisateur avant de connecter toute logique. Voici un prototype plus élaboré du même composant, toujours « contrôlé » par la propstatus :
Étape 2 : Déterminez ce qui déclenche ces changements d'état
Vous pouvez déclencher des mises à jour d'état en réponse à deux types d'entrées :
- Entrées humaines,comme cliquer sur un bouton, saisir dans un champ, naviguer via un lien.
- Entrées informatiques,comme l'arrivée d'une réponse réseau, l'achèvement d'un délai d'attente, le chargement d'une image.


Illustrations parRachel Lee Nabors
Dans les deux cas,vous devez définir desvariables d'étatpour mettre à jour l'interface utilisateur.Pour le formulaire que vous développez, vous devrez changer d'état en réponse à quelques entrées différentes :
- Modifier le champ de saisie(humain) doit le faire passer de l’étatVideà l’étatSaisieou inversement, selon que la zone de texte est vide ou non.
- Cliquer sur le bouton Envoyer(humain) doit le faire passer à l’étatEnvoi.
- Une réponse réseau réussie(ordinateur) doit le faire passer à l’étatSuccès.
- Une réponse réseau échouée(ordinateur) doit le faire passer à l’étatErreuravec le message d’erreur correspondant.
Remarque
Notez que les entrées humaines nécessitent souvent desgestionnaires d’événements!
Pour visualiser ce flux, essayez de dessiner chaque état sur papier sous forme de cercle étiqueté, et chaque changement entre deux états sous forme de flèche. Vous pouvez ainsi esquisser de nombreux flux et corriger les bogues bien avant l’implémentation.


États du formulaire
Étape 3 : Représenter l’état en mémoire avecuseState
Ensuite, vous devrez représenter les états visuels de votre composant en mémoire avecuseState.La simplicité est essentielle : chaque élément d’état est une « pièce mobile », etvous voulez le moins de « pièces mobiles » possible.Plus de complexité entraîne plus de bogues !
Commencez par l’état quidoit absolumentêtre présent. Par exemple, vous devrez stocker laanswerpour la saisie, et l’error(si elle existe) pour stocker la dernière erreur :
Ensuite, vous aurez besoin d’une variable d’état représentant lequel des états visuels vous souhaitez afficher. Il y a généralement plusieurs façons de représenter cela en mémoire, vous devrez donc expérimenter.
Si vous avez du mal à trouver immédiatement la meilleure façon, commencez par ajouter suffisamment d’états pour êtrecertainque tous les états visuels possibles sont couverts :
Votre première idée ne sera probablement pas la meilleure, mais ce n’est pas grave — le refactoring de l’état fait partie du processus !
Étape 4 : Supprimer les variables d’état non essentielles
Vous devez éviter la duplication dans le contenu de l’état pour ne suivre que l’essentiel. Passer un peu de temps à refactorer la structure de votre état rendra vos composants plus faciles à comprendre, réduira la duplication et évitera les significations involontaires. Votre objectif est deempêcher les cas où l’état en mémoire ne représente aucune interface utilisateur valide que vous voudriez montrer à un utilisateur.(Par exemple, vous ne voulez jamais afficher un message d’erreur et désactiver la saisie en même temps, sinon l’utilisateur ne pourra pas corriger l’erreur !)
Voici quelques questions que vous pouvez poser sur vos variables d’état :
- Cet état crée-t-il un paradoxe ?Par exemple,
isTypingetisSubmittingne peuvent pas être tous deuxtrue. Un paradoxe signifie généralement que l'état n'est pas suffisamment contraint. Il existe quatre combinaisons possibles pour deux booléens, mais seulement trois correspondent à des états valides. Pour supprimer l'état « impossible », vous pouvez les combiner en unstatusqui doit être l'une de ces trois valeurs :'typing','submitting', ou'success'. - La même information est-elle déjà disponible dans une autre variable d'état ?Un autre paradoxe :
isEmptyetisTypingne peuvent pas êtretrueen même temps. En les gardant comme variables d'état séparées, vous risquez qu'elles se désynchronisent et causent des bugs. Heureusement, vous pouvez supprimerisEmptyet vérifier plutôtanswer.length === 0. - Pouvez-vous obtenir la même information à partir de l'inverse d'une autre variable d'état ?
isErrorn'est pas nécessaire car vous pouvez vérifiererror !== nullà la place.
Après ce nettoyage, il vous reste 3 (contre 7 initialement !) variables d'étatessentielles :
Vous savez qu'elles sont essentielles, car vous ne pouvez en supprimer aucune sans casser la fonctionnalité.
Étape 5 : Connecter les gestionnaires d'événements pour définir l'état
Enfin, créez des gestionnaires d'événements qui mettent à jour l'état. Voici le formulaire final, avec tous les gestionnaires d'événements connectés :
Bien que ce code soit plus long que l'exemple impératif original, il est beaucoup moins fragile. Exprimer toutes les interactions comme des changements d'état vous permet d'introduire plus tard de nouveaux états visuels sans casser les existants. Cela vous permet également de changer ce qui doit être affiché dans chaque état sans modifier la logique de l'interaction elle-même.
Récapitulatif
- La programmation déclarative consiste à décrire l'interface utilisateur pour chaque état visuel plutôt que de micro-gérer l'interface (programmation impérative).
- Lors du développement d'un composant :
- Identifiez tous ses états visuels.
- Déterminez les déclencheurs humains et informatiques des changements d'état.
- Modélisez l'état avec
useState. - Supprimez les états non essentiels pour éviter les bugs et les paradoxes.
- Connectez les gestionnaires d'événements pour définir l'état.
Try out some challenges
Challenge 1 of 3:Add and remove a CSS class #
Make it so that clicking on the picture removes the background--active CSS class from the outer <div>, but adds the picture--active class to the <img>. Clicking the background again should restore the original CSS classes.
Visually, you should expect that clicking on the picture removes the purple background and highlights the picture border. Clicking outside the picture highlights the background, but removes the picture border highlight.
