Comment devenir un pro avec React setState () en 10 minutes

Cet article s'adresse aux personnes qui ont déjà eu leur première approche de React, et qui, en tant que débutants, ont des doutes sur son setStatefonctionnement et sur la manière de l'utiliser correctement. Cela devrait également aider les développeurs de niveau intermédiaire à senior à utiliser des moyens plus propres et plus abstraits de définir l'état, et à faire en sorte que les fonctions d'ordre supérieur gèrent et réduisent l'état abstrait.

Lisez et amusez-vous!

Alors prenez une tasse de café et continuez à lire! ?

Concepts de base de setState ()

Les composants React vous permettent de diviser l'interface utilisateur (UI) en éléments indépendants et réutilisables, afin que vous puissiez penser à chaque élément de manière isolée.

Conceptuellement, les composants sont comme des fonctions JavaScript. Ils acceptent des entrées arbitraires (appelées «accessoires») et renvoient des éléments React décrivant ce qui devrait apparaître à l'écran.

Si vous avez besoin de donner à l'utilisateur la possibilité de saisir quelque chose ou de modifier d'une manière ou d'une autre les variables que le composant reçoit comme accessoires, vous en aurez besoin setState.

Que vous déclariez un composant en tant que fonction ou classe, il ne doit jamais modifier ses propres accessoires.

Tous les composants Reactdoivent agir comme de pures fonctions par rapport à leurs accessoires. Cela signifie des fonctions qui n'essaient jamais de changer leurs entrées et retournent toujours le même résultat pour les mêmes entrées.

Bien entendu, les interfaces utilisateur des applications sont dynamiques et évoluent avec le temps. C'est pourquoi a stateété créé.

State permet aux composants React de modifier leur sortie au fil du temps en réponse aux actions des utilisateurs, aux réponses du réseau et à toute autre chose, sans enfreindre cette règle.

Les composants définis comme des classes ont des fonctionnalités supplémentaires. L'état local est une fonctionnalité disponible uniquement pour les composants de classe.

setState est la méthode API fournie avec la bibliothèque afin que l'utilisateur puisse définir et manipuler l'état au fil du temps.

Trois règles de pouce lors de l'utilisation de setState ()

Ne pas modifier l'état directement

Les mises à jour d'état peuvent être asynchrones

React peut regrouper plusieurs setState()appels en une seule mise à jour pour les performances.

Étant donné que this.props et this.statepeut être mis à jour de manière asynchrone, vous ne devez pas vous fier à leurs valeurs pour calculer l'état suivant.

Vous devez toujours faire ce genre de manipulation avec une approche fonctionnelle, en fournissant le stateet propset en renvoyant le nouveau statebasé sur l'ancien.

Les mises à jour d'état sont fusionnées

Lorsque vous appelez setState(), React fusionne l'objet que vous fournissez dans le fichier courant state.

Dans l'exemple ci-dessous, nous mettons à jour la variable dogNeedsVaccinationindépendamment des autres statevariables.

La fusion est superficielle, this.setState({ dogNeedsVaccination: true }) laisse donc les autres variables intactes, en remplaçant uniquement la valeur de dogNeedsVaccination.

Respectez le flux de données et évitez d'indiquer le maximum

Les données s'écoulent! Ni les composants parents ni les composants enfants ne peuvent savoir si un certain composant est avec état ou sans état, et ils ne devraient pas se soucier de savoir s'il est défini comme une fonction ou une classe.

C'est pourquoi il stateest souvent appelé local ou encapsulé. Il n'est accessible à aucun composant autre que celui qui le possède et le définit.

Lorsque vous setStateutilisez un accessoire et que vous l'utilisez dans votre composant, vous interrompez le flux des accessoires de rendu. Si pour une raison quelconque, l'accessoire passé dans votre composant a changé dans le composant parent, l'enfant ne sera pas rendu automatiquement par magie?!

Vérifions un exemple:

Ici, vous avez un Homecomposant qui génère un nombre magique toutes les 1000 ms et le définit lui-même state.

Après cela, il rend le nombre et invoque trois Childcomposants (frères et sœurs) qui recevront le nombre magique dans le but de l'afficher en utilisant trois approches différentes:

Première approche

Le composant ChildOfHomerespecte le flux en cascade des accessoires React et, étant donné que l'objectif est uniquement de montrer le nombre magique, il rend propsdirectement le reçu.

Deuxième approche

Le composant ChildOfHomeBrotherreçoit le propsde son parent et, en l'invoquant componentDidMount, définit le nombre magique en state. Ensuite, il rend le fichier state.magicNumber.

Cet exemple ne fonctionne pas car render()il ne sait pas que a prop a changé et ne déclenche donc pas le nouveau rendu du composant. Comme le composant n'est plus rendu, il componentDidMountn'est plus appelé et l'affichage n'est pas mis à jour.

Troisième approche

Habituellement, lorsque nous essayons de le faire fonctionner en utilisant la deuxième approche, nous pensons qu'il manque quelque chose. Au lieu de prendre du recul, nous continuons d'ajouter des éléments au code pour le faire fonctionner!

Donc, dans cette troisième approche, nous avons ajouté componentDidUpdatepour vérifier s'il y a un changement propspour déclencher le re-rendu du composant. Ceci est inutile et nous conduit à un code impur. Cela entraîne également des coûts de performance qui seront multipliés par le nombre de fois que nous le faisons dans une grande application où nous avons beaucoup de composants enchaînés et d'effets secondaires.

C'est faux sauf si vous devez autoriser l'utilisateur à modifier la valeur prop reçue.

Si vous n'avez pas besoin de changer la valeur de l'accessoire, essayez toujours de faire fonctionner les choses selon le flux React (première approche).

Vous pouvez consulter une page Web fonctionnelle avec cet exemple que j'ai préparé pour vous dans Glitch. Jetez un œil et amusez-vous?

Consultez également le code dans le Home.jset HomeCodeCleaned.js(sans les éléments HTML) dans mon référentiel à propos de cet article.

Comment définir l'état

Donc à ce stade, je pense qu'il est temps de se salir les mains!

Jouons un peu avec setStateet améliorons-le! Suivez simplement et prenez une autre tasse de café!

Créons un petit formulaire pour mettre à jour les données utilisateur:

Voici le code de l'exemple ci-dessus:

Nous définissons statecomme un objet, et il n'y a pas de problème car notre état actuel ne dépend pas de notre dernier état.

Et si nous créons un autre champ de formulaire pour introduire et afficher le nom de famille?

Agréable! Nous avons résumé la handleFormChangeméthode pour pouvoir gérer tous les champs de saisie et setState.

Et si nous ajoutions un bouton bascule pour marquer les données comme valides ou non valides et un compteur pour savoir combien de modifications nous avons apportées à l'état?

Ouais! Nous basculons! Nous avons résumé beaucoup de choses!

Hmmm… Disons que je ne veux pas qu'une case à cocher contrôle la isValidvariable mais un simple bouton bascule.

Séparons également le gestionnaire de compteur de cette méthode. Cela fonctionne bien, mais dans des situations plus complexes où React a besoin de lots / grouper les modifications, ce n'est pas une bonne politique de s'appuyer sur la this.state.countervariable pour en ajouter une de plus. Cette valeur peut changer sans que vous en soyez conscient.

Nous en utilisons une copie superficielle au moment où l'opération est appelée, et à ce moment précis, vous ne savez pas si sa valeur est celle que vous attendiez ou non!

Allons un peu fonctionnel!

D'accord - Nous avons perdu l'abstraction parce que nous avons séparé les gestionnaires, mais c'est pour une bonne raison!

Donc, pour le moment, nous continuons à handleFormChangepasser un objet à la setStateméthode API. Mais les méthodes handleCounteret handleIsValidsont maintenant fonctionnelles et commencent par saisir l'état actuel, puis, en fonction de cet état, le changer pour le suivant.

C'est la manière correcte de changer les statevariables qui dépendent de l'état précédent.

Que se passe-t-il si nous voulons console.log()indiquer les modifications des formulaires firstNameet lastNamedes formulaires d'entrée à chaque fois qu'une modification se produit? Essayons!

Agréable! Chaque fois que le handleFormChangese produit (ce qui signifie qu'une nouvelle pression de touche s'est produite), la logFields()méthode est invoquée et enregistre l'état actuel dans la console!

Vérifions la console du navigateur:

Attendez! Que s'est-il passé ici? Le journal de la console est un changement avant l'entrée du formulaire actuel! Pourquoi cela arrive-t-il?

setState est asynchrone !!

Nous le savions déjà mais maintenant nous le voyons avec nos yeux! Ce qui se passe là-bas? Jetons un coup d'œil aux méthodes handleFormChangeet logFieldsci-dessus.

Ainsi, la handleFormChangeméthode reçoit le nom et la valeur de l'événement, puis effectue une setStatede ces données. Ensuite, il appelle le handleCounterpour mettre à jour les informations du compteur, et à la fin appelle la logFieldsméthode. La logFieldsméthode saisit le currentStateet retourne «Eduard» au lieu de «Eduardo».

La chose est: setStateest asynchrone et n'agit pas sur le moment. React fait son travail et exécute la logFieldsméthode en premier, partant setStatepour la prochaine boucle d'événements.

Mais comment éviter ce genre de situation?

Eh bien, l' setStateAPI a callbackpour éviter cette situation:

Si nous voulons que le logFields()prenne en compte les modifications récentes que nous avons apportées à l'état, nous devons l'invoquer dans le rappel, comme ceci:

Ok, maintenant ça marche!

Nous disons à React: «Hey React! Méfiez-vous que lorsque vous invoquez la logFieldsméthode, je veux que vous ayez statedéjà mis à jour, d'accord? Je compte sur toi!"

React dit: «D'accord Edo! Je vais gérer tout ce lot de trucs que je fais habituellement dans la cour avec le setStatetruc et seulement quand j'en aurai fini avec ça, je l'invoquerai logFields()! Homme cool! Se détendre!"

Et en fait - cela a fonctionné!

Ok tout le monde! À cette époque, nous avons surmonté les principaux pièges de setState.

Avez-vous le courage de dépasser le mur? Prends une tasse de café et prenons vraiment du kewl…

Se faire plaisir avec setState ()

Maintenant que nous avons handleCounteret des handleIsValidméthodes, et setState()exprimé avec des fonctions, nous pouvons composer la mise à jour de l'état avec d'autres fonctions! Moi j'aime la composition! Amusons-nous!

Nous pouvons prendre la logique à l'intérieur setStated'une fonction en dehors du composant de classe. Appelons ça toggleIsValid. ☝️

Désormais, cette fonction peut vivre en dehors du composant de classe, n'importe où dans votre application.

Et si nous utilisons une fonction d'ordre supérieur?

Hou la la! Maintenant, nous n'invoquons plus la toggleIsValidfonction. Nous invoquons une fonction abstraite d'ordre supérieur appelée toggleKeyet y passons une clé (chaîne dans ce cas).

Comment devons-nous changer la toggleIsValidfonction maintenant?

Quoi?! Nous avons maintenant une fonction appelée toggleKeyqui reçoit a keyet retourne une nouvelle fonction qui change d'état en fonction de la clé fournie.

Cela toggleKeypeut être dans une bibliothèque ou dans un fichier d'aide. Il peut être invoqué dans de nombreux contextes différents pour changer l'état de tout ce que vous voulez en son contraire.

Génial!

Faisons de même avec le gestionnaire de compteur d'incrémentation:

Ouais! Ça marche! Vraiment gentil. Soyons fous maintenant ...

Photographier la lune et revenir

Que faire si nous créons une makeUpdaterfonction générique qui reçoit la fonction de transformation que vous souhaitez appliquer, prend la clé et renvoie la fonction d'état gérant l'état avec la fonction de transformation et la clé? Un peu confus? Allons-y!

Ok c'est assez… Arrêtons-nous ici. ?

Vous pouvez vérifier tout le code que nous avons créé dans ce dépôt GitHub.

Enfin et surtout

N'oubliez pas d'éviter le max en utilisant l'état et de respecter la cascade d'accessoires de rendu React.

N'oubliez pas que setStatec'est asynchrone.

N'oubliez pas que vous setStatepouvez prendre un objet ou une fonction

N'oubliez pas que vous devez transmettre une fonction lorsque votre état suivant dépend de votre état précédent.

Bibliographie

  1. Documentation React
  2. Atteignez les cours techniques de Ryan Florence, que je recommande vraiment.

Merci beaucoup!