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?
