Dans la partie d'aujourd'hui de la traduction du cours React, nous vous suggérons de terminer la prochaine tâche pratique et de présenter à votre attention une histoire sur la façon de modifier l'état des composants React.

→ 
Partie 1: aperçu du cours, raisons de la popularité de React, ReactDOM et JSX→ 
Partie 2: composants fonctionnels→ 
Partie 3: fichiers composants, structure du projet→ 
Partie 4: composants parent et enfant→ 
Partie 5: début des travaux sur une application TODO, les bases du style→ 
Partie 6: sur certaines fonctionnalités du cours, JSX et JavaScript→ 
Partie 7: styles en ligne→ 
Partie 8: poursuite des travaux sur l'application TODO, familiarité avec les propriétés des composants→ 
Partie 9: propriétés des composants→ 
Partie 10: Atelier sur l'utilisation des propriétés et du style des composants→ 
Partie 11: génération de balisage dynamique et méthode des tableaux de cartes→ 
Partie 12: atelier, troisième étape de travail sur une application TODO→ 
Partie 13: composants basés sur les classes→ 
Partie 14: atelier sur les composants basés sur les classes, état des composants→ 
Partie 15: ateliers santé composante→ 
Partie 16: quatrième étape de travail sur une application TODO, gestion d'événements→ 
Partie 17: cinquième étape de travail sur une application TODO, modifiant l'état des composants→ 
Partie 18: la sixième étape de travail sur une application TODO→ 
Partie 19: méthodes du cycle de vie des composantsPartie 20: la première leçon de rendu conditionnel→ 
Partie 21: deuxième leçon et atelier sur le rendu conditionnel→ 
Partie 22: la septième étape des travaux sur une application TODO, téléchargement de données depuis des sources externes→ 
Partie 23: première leçon sur l'utilisation des formulaires→ 
Partie 24: Deuxième leçon sur les formulaires→ 
Partie 25: Atelier sur l'utilisation des formulaires→ 
Partie 26: architecture d'application, modèle de conteneur / composant→ 
Partie 27: projet de coursLeçon 31. Atelier. Application TODO. Étape numéro 5
→ 
Original▍Emploi
Lors du lancement de notre application Todo, vous pouvez remarquer qu'une notification s'affiche dans la console qui indique que nous, après avoir configuré la propriété 
checked d'un élément dans le composant 
TodoItem , n'avons pas fourni de mécanisme pour interagir avec cet élément sous la forme d'un 
onChange événements 
onChange . Lorsque vous travaillez avec l'interface d'application, cela se traduit par le fait que les indicateurs affichés sur la page ne peuvent pas être cochés ou décochés.
Ici, vous êtes invité à équiper un élément du type 
checkbox du composant 
TodoItem d'un gestionnaire d'événements onChange, qui, à ce stade du travail, est suffisant pour se présenter sous la forme d'une fonction qui renvoie quelque chose à la console.
▍Solution
Voici à quoi ressemble le code du composant 
TodoItem maintenant, qui est stocké dans le fichier 
TodoItem.js :
 import React from "react" function TodoItem(props) {   return (       <div className="todo-item">           <input type="checkbox" checked={props.item.completed}/>           <p>{props.item.text}</p>       </div>   ) } export default TodoItem 
C'est ce que la console affiche au démarrage de l'application.
Notification de la consoleEn même temps, les drapeaux ne répondent pas à nos effets.
Afin de se débarrasser de cette notification et de préparer le projet pour d'autres travaux, il suffit d'attribuer un 
onChange événements 
onChange à l'élément de 
checkbox à 
checkbox . Voici à quoi cela ressemble dans le code:
 import React from "react" function TodoItem(props) {   return (       <div className="todo-item">           <input               type="checkbox"               checked={props.item.completed}               onChange={() => console.log("Changed!")}           />           <p>{props.item.text}</p>       </div>   ) } export default TodoItem 
Ici, en tant que gestionnaire, nous utilisons une fonction simple qui génère le mot 
Checked! sur la console 
Checked! . Dans le même temps, cliquer sur les drapeaux n'entraîne pas de changement dans leur état, mais la notification de la console, comme on peut le voir sur la figure suivante, disparaît.
Les indicateurs ne fonctionnent toujours pas, mais la notification de la console a disparuCette petite modification apportée à l'application nous permettra, après avoir traité la modification de l'état des composants, de faire fonctionner correctement les cases à cocher.
Leçon 32. Modification de l'état des composants
→ 
OriginalCommençons par une application standard créée à l'aide de 
create-react-app App.js create-react-app , dans le fichier 
App.js qui contient le code suivant:
 import React from "react" class App extends React.Component {   constructor() {       super()       this.state = {           count: 0       }   }     render() {       return (           <div>               <h1>{this.state.count}</h1>               <button>Change!</button>           </div>       )   } } export default App 
Le 
index.css styles 
index.css , qui est 
index.js dans le fichier 
index.js , contient la description des styles suivante:
 div {   display: flex;   flex-direction: column;   align-items: center;   justify-content: center; } h1 {   font-size: 3em; } button {   border: 1px solid lightgray;   background-color: transparent;   padding: 10px;   border-radius: 4px;  } button:hover {   cursor: pointer; } button:focus {   outline:0; } 
À ce stade, l'application ressemble à celle illustrée dans la figure suivante.
Page d'application dans le navigateurAujourd'hui, nous allons parler de la façon de changer l'état des composants. Si le composant a un état, cela permet, en l'initialisant, d'y stocker des données. Mais si l'état ne pouvait pas être changé, le composant ne bénéficierait pas particulièrement de sa présence, le stockage des données ne serait pas très différent, par exemple, de leur copie papier dans le code du composant.
Parlons de l'application, sur l'exemple dont nous allons envisager de travailler avec l'état du composant. Le composant 
App dont le code est présenté ci-dessus est un composant basé sur une classe. C'est assez évident, car nous avons besoin de ce composant pour avoir un état. Dans le code du composant, nous utilisons le constructeur.
Dans ce document, nous appelons, comme toujours, la méthode 
super() et initialisons l'état en lui écrivant la propriété 
count et en lui affectant une valeur initiale de 
0 . Dans la méthode 
render() , nous imprimons un en-tête de premier niveau représentant la valeur de la propriété 
count partir de l'état du composant, ainsi qu'un bouton avec le mot 
Change! . Tout cela est formaté à l'aide de styles.
Si, à ce stade du travail sur l'application, ouvrez-la dans un navigateur et cliquez sur le bouton, alors, bien sûr, rien ne se passera. Mais nous devons cliquer sur le bouton pour changer l'état du composant, affectant sa propriété 
count . Dans le même temps, nous avons déjà étudié la méthodologie de gestion des événements dans React, et notre tâche est de créer un mécanisme qui, en répondant à un clic sur un bouton, modifie la propriété d'état de 
count .
Passons à la résolution de notre problème en équipant le bouton d'un 
onClick événements 
onClick , qui, pour commencer, produira simplement quelque chose sur la console.
Pour ce faire, nous allons ajouter une nouvelle méthode à la classe de composants. Vous pouvez l'appeler comme bon vous semble, mais il est d'usage d'appeler de telles méthodes pour que leurs noms indiquent les événements qu'elles traitent. Par conséquent, comme nous allons l'utiliser pour traiter l'événement 
click , nous l'appelons 
handleClick() . Voici à quoi ressemblera maintenant le code du composant 
App .
 import React from "react" class App extends React.Component {   constructor() {       super()       this.state = {           count: 0       }   }     handleClick() {       console.log("I'm working!")   }     render() {       return (           <div>               <h1>{this.state.count}</h1>               <button onClick={this.handleClick}>Change!</button>           </div>       )   } } export default App 
Veuillez noter qu'en faisant référence à cette méthode à partir de 
render() , nous utilisons une construction du formulaire 
this.handleClick .
Maintenant, si vous cliquez sur le bouton, le message correspondant apparaîtra dans la console.
Cliquer sur le bouton appelle la méthode de classe.Maintenant, faisons en sorte que cliquer sur le bouton augmente le nombre affiché au-dessus, c'est-à-dire modifier l'état du composant. Essayez peut-être de changer directement l'état du composant, dans la méthode 
handleClick() ? Disons que si nous réécrivons cette méthode comme ceci:
 handleClick() {   this.state.count++ } 
Je dois dire tout de suite que cela ne fonctionne pas avec l'état des composants dans React. Tenter d'exécuter un tel code générera une erreur.
L'état du composant peut être comparé aux vêtements qu'une personne porte. S'il veut changer de vêtements, il ne modifie pas ou ne repeint pas les vêtements sans se retirer, mais l'enlève et met autre chose. En fait, c'est exactement ainsi qu'ils fonctionnent avec l'état des composants.
Vous vous souvenez peut-être que nous parlions d'une méthode spéciale utilisée pour modifier l'état, disponible dans les composants basés sur les classes car ils étendent la classe 
React.Component . Il s'agit de la méthode 
setState() . Il est utilisé dans les cas où vous devez modifier l'état d'un composant. Cette méthode peut être utilisée de différentes manières.
Rappelons qu'un état est un objet. Essayons de passer à la méthode 
setState() un objet qui remplacera l'état. Nous 
handleClick() méthode 
handleClick() ceci:
 handleClick() {   this.setState({ count: 1 }) } 
Tenter d'utiliser cette méthode provoquera l'erreur suivante: 
TypeError: Cannot read property 'setState' of undefined . En fait, ce dont nous parlons maintenant suscite beaucoup de controverse parmi les développeurs de React, et maintenant je vais vous montrer un moyen très simple de résoudre ce problème, qui, à première vue, peut sembler inhabituel.
Le fait est qu'à chaque fois, en créant une méthode de classe ( 
handleClick() dans notre cas), dans laquelle il est prévu d'utiliser la méthode 
setState() , cette méthode doit y être associée. Cela se fait dans le constructeur. Le code du composant après cette modification ressemblera à ceci:
 import React from "react" class App extends React.Component {   constructor() {       super()       this.state = {           count: 0       }       this.handleClick = this.handleClick.bind(this)   }     handleClick() {       this.setState({ count: 1 })   }     render() {       return (           <div>               <h1>{this.state.count}</h1>               <button onClick={this.handleClick}>Change!</button>           </div>       )   } } export default App 
Maintenant, après avoir cliqué sur le bouton 
Change! le numéro 1 apparaîtra au-dessus, les messages d'erreur ne seront pas affichés.
Appuyer sur un bouton modifie l'étatCertes, le bouton s'est avéré être «ponctuel». Après le premier clic dessus, 
0 passe à 
1 , et si vous cliquez à nouveau dessus, rien ne se passera. En général, cela n'est pas surprenant. Le code appelé lorsque le bouton est cliqué fait son travail, chaque fois que vous changez l'état en un nouveau, cependant, après le premier clic sur le bouton, le nouvel état, dans lequel le numéro 
1 est stocké dans la propriété 
count , ne diffère pas de l'ancien. Afin de résoudre ce problème, envisagez une autre façon de travailler avec la méthode 
setState() .
Si nous ne sommes pas intéressés par l'état précédent du composant, nous pouvons simplement passer un objet à cette méthode, qui remplacera l'état. Mais il arrive souvent que le nouvel état d'un composant dépend de l'ancien. Dans notre cas, cela signifie que, sur la base de la valeur de la propriété 
count , qui est stockée dans la version précédente de l'état, nous voulons ajouter 1 à cette valeur. Dans les cas où pour modifier l'état, vous devez être conscient de ce qui y était précédemment stocké, vous pouvez transmettre à la méthode 
setState() une fonction qui, en tant que paramètre, reçoit la version précédente de l'état. Vous pouvez nommer ce paramètre comme vous le souhaitez, dans notre cas ce sera 
prevState . L'achat de cette fonction ressemblera à ceci:
 handleClick() {   this.setState(prevState => {             }) } 
Vous pourriez penser que dans une telle fonction, il suffit de se référer simplement à l'état en utilisant une construction de la forme 
this.state , mais cette approche ne nous conviendra pas. Par conséquent, il est important que cette fonction accepte la version précédente de l'état du composant.
La fonction doit renvoyer une nouvelle version de l'état. Voici à quoi 
handleClick() méthode 
handleClick() pour 
handleClick() ce problème:
 handleClick() {   this.setState(prevState => {       return {           count: prevState.count + 1       }   }) } 
Notez que pour obtenir la nouvelle valeur de la propriété 
count , nous utilisons la construction 
count: prevState.count + 1 . Vous pourriez penser qu'une construction du 
count: prevState.count++ formulaires 
count: prevState.count++ , mais l'opérateur 
++ count: prevState.count++ variable à laquelle il est appliqué, cela signifiera une tentative de modifier la version précédente de l'état, nous ne l'utilisons donc pas ici.
Le code complet du fichier composant à ce stade ressemblera à ceci:
 import React from "react" class App extends React.Component {   constructor() {       super()       this.state = {           count: 0       }       this.handleClick = this.handleClick.bind(this)   }     handleClick() {       this.setState(prevState => {           return {               count: prevState.count + 1           }       })   }       render() {       return (           <div>               <h1>{this.state.count}</h1>               <button onClick={this.handleClick}>Change!</button>           </div>       )   } } export default App 
Maintenant, chaque clic sur le bouton augmente la valeur du compteur.
Chaque clic sur le bouton augmente la valeur du compteur.Ce que nous venons de découvrir nous ouvre de grandes opportunités dans le développement d'applications React.
Nous avons dit précédemment qu'un composant parent peut, via un mécanisme de propriété, transmettre des propriétés de son propre état aux composants enfants. Si React détecte un changement d'état du composant parent, il restitue le composant enfant auquel cet état est transmis. Cela ressemble à un appel à la méthode 
render() . Par conséquent, le composant enfant reflétera les nouvelles données stockées dans l'état du composant parent.
Résumé
Aujourd'hui, vous avez préparé l'application Todo pour poursuivre les travaux, et vous vous êtes également familiarisé avec les mécanismes utilisés dans React pour modifier l'état d'un composant. La prochaine fois, il vous sera demandé d'étendre les capacités de l'application de formation en utilisant ce que vous avez appris aujourd'hui.
Chers lecteurs! Que pensez-vous du fait que l'état des composants dans React ne peut pas être modifié directement sans utiliser des mécanismes spéciaux?
