Dans la partie d'aujourd'hui de la traduction du cours de formation React, vous êtes invité à remplir une tâche de formulaire.

→
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 43. Atelier. Travailler avec des formulaires
→
Original▍Emploi
Dans cette leçon pratique, vous êtes invité à afficher le code du composant
App
, qui se trouve dans le fichier
App.js
du projet standard créé par create-react-app. Voici le code:
import React, {Component} from "react" class App extends Component { constructor() { super() this.state = {} } render() { return ( <main> <form> <input placeholder="First Name" /><br /> <input placeholder="Last Name" /><br /> <input placeholder="Age" /><br /> {/* */} <br /> {/* */} <br /> {/* */} <br /> <button>Submit</button> </form> <hr /> <h2><font color="#3AC1EF">Entered information:</font></h2> <p>Your name: {/* */}</p> <p>Your age: {/* */}</p> <p>Your gender: {/* */}</p> <p>Your destination: {/* */}</p> <p> Your dietary restrictions: {/* */} </p> </main> ) } } export default App
En général, votre tâche consiste à vous assurer que les données que l'utilisateur saisit lors de l'utilisation des contrôles de formulaire apparaissent immédiatement dans le texte sous ce formulaire. Tirez parti de la technologie des
composants gérés lorsque vous terminez la tâche. Il est à noter que la tâche qui vous est proposée est une version adaptée de
cette tâche, vous pouvez donc y jeter un œil afin de mieux comprendre les fonctionnalités des contrôles que vous êtes invité à créer et configurer.
Voici ce que le composant affiche désormais à l'écran.
Application dans le navigateur▍Solution
Vous pouvez aborder la solution du problème qui vous est proposé sous différents angles. Nous commencerons par mettre tout ce dont nous avons besoin dans l'état, après quoi nous mettrons en place les contrôles et autres mécanismes du composant.
Pour le moment, l'état du composant ressemblera à celui ci-dessous.
this.state = { firstName: "", lastName: "", age: 0, gender: "", destination: "", dietaryRestrictions: [] }
Il ne faut pas oublier que lors du travail sur un programme, il peut s'avérer, par exemple, qu'il sera plus pratique d'initialiser un état différemment. Si nous rencontrons quelque chose de similaire, nous changerons le code d'initialisation de l'état. En particulier, certains doutes peuvent maintenant être causés par le nombre 0 écrit dans la propriété
age
, dans lequel il est censé stocker l'âge entré par l'utilisateur. Peut-être faudra-t-il faire autrement avec le système de stockage de données de drapeau, qui est maintenant représenté par la propriété
dietaryRestrictions
, initialisée par un tableau vide.
Maintenant, après l'initialisation de l'état, prenons soin de configurer les contrôles. Étant donné que le code a déjà une description des champs de saisie - commençons par eux.
Ces contrôles devront être nommés en définissant leurs attributs de
name
afin qu'ils correspondent aux noms des propriétés d'état dans lesquelles les données entrées dans ces champs seront stockées. Ils doivent avoir un attribut
value
dont la valeur est déterminée en fonction des données stockées dans l'état. Lorsque vous saisissez des données dans chacun de ces champs, vous devez transmettre les données entrées au composant, ce qui
onChange
à disposer d'un
onChange
événements
onChange
. Toutes ces considérations conduisent au fait que la description des champs ressemble maintenant à ceci:
<input name="firstName" value={this.state.firstName} onChange={this.handleChange} placeholder="First Name" /> <br /> <input name="lastName" value={this.state.lastName} onChange={this.handleChange} placeholder="Last Name" /> <br /> <input name="age" value={this.state.age} onChange={this.handleChange} placeholder="Age" />
En tant que méthode utilisée pour traiter les événements
this.handleChange
de ces champs,
this.handleChange
est toujours inexistant. Créez cette méthode:
handleChange(event) { const {name, value} = event.target this.setState({ [name]: value }) }
Ici, nous extrayons les propriétés de
name
et de
value
de l'objet
event.target
, puis les utilisons pour définir la propriété d'état correspondante. Pour le moment, un tel code de gestionnaire d'événements universel nous conviendra, mais plus tard, lorsque nous travaillerons avec des indicateurs, nous y apporterons des modifications.
N'oubliez pas
this
liaison effectuée dans le constructeur du composant:
this.handleChange = this.handleChange.bind(this)
Afin d'obtenir une sortie au bas de la page de données entrées dans les champs
firstName
,
secondName
et
age
,
secondName
travaillerons avec les éléments
<p>
correspondants, en les amenant à la forme suivante:
<p>Your name: {this.state.firstName} {this.state.lastName}</p> <p>Your age: {this.state.age}</p>
Voyons maintenant ce que nous avons obtenu.
Application dans le navigateurComme vous pouvez le voir, dans le champ de saisie de l'âge, aucun indice ne s'affiche. Au lieu de cela, ce qui est défini dans la propriété state of
age
s'affiche, c'est-à-dire 0. Nous avons besoin d'un indice dans le champ vide. Essayons de remplacer la valeur de
age
in state par
null
. Après cela, il s'avère que le formulaire ressemble à ce qu'il devrait être, mais l'avertissement suivant s'affiche dans la console concernant le champ d'
age
:
Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components
Par conséquent, nous devrons remplacer la valeur de la propriété state
age
par une chaîne vide, ce qui apportera le code d'initialisation de l'état au format suivant:
this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", dietaryRestrictions: [] }
Essayez maintenant le formulaire. Immédiatement après l'ouverture, il aura la même apparence qu'au tout début du travail, c'est-à-dire que l'invite retournera dans le champ d'
age
. Lorsque vous remplissez les champs, les données saisies seront affichées en bas de la page.
Application dans le navigateurComme vous pouvez le voir, à ce stade du travail, tout fonctionne comme prévu.
Nous allons maintenant nous engager dans de nouveaux éléments. La prochaine étape du travail sur le formulaire consistera à y ajouter des commutateurs.
Enveloppez les commutateurs dans la
<label>
, ce qui nous permettra non seulement de signer le commutateur, mais également de nous assurer que le fait de cliquer sur cette signature, c'est-à-dire sur son élément parent, mène à sa sélection.
Lorsque vous travaillez avec des commutateurs, il convient de se rappeler qu'il s'agit d'une sorte de combinaison d'indicateurs avec l'attribut
checked
et les champs de texte qui ont l'attribut
value
. Les commutateurs forment un groupe dans lequel chacun des commutateurs porte le même nom, et la propriété
checked
des commutateurs est définie en fonction d'une condition configurée de sorte qu'il serait impossible d'activer plus d'un commutateur faisant partie du même groupe.
onChange
comme gestionnaire d'événements pour les commutateurs
onChange
.
Par conséquent, le code de description du commutateur ressemblera à ceci:
<label> <input type="radio" name="gender" value="male" checked={this.state.gender === "male"} onChange={this.handleChange} /> Male </label> <br /> <label> <input type="radio" name="gender" value="female" checked={this.state.gender === "female"} onChange={this.handleChange} /> Female </label>
Nous allons maintenant traiter l'élément
<p>
correspondant situé en bas de la page, comme suit:
<p>Your gender: {this.state.gender}</p>
Après cela, le formulaire peut être testé. Immédiatement après le démarrage, les deux commutateurs sont désélectionnés, car l'état stocke une valeur qui ne permet à aucune des vérifications effectuées lors de la définition de leur propriété
checked
de
checked
true
. Après avoir cliqué sur l'un d'eux, la valeur correspondante tombe dans l'état (stockée dans l'attribut
value
du commutateur), le commutateur est sélectionné, le texte correspondant est affiché en bas du formulaire.
Application dans le navigateurMaintenant, travaillons sur la zone de liste déroulante. Sa pièce ressemble à ceci:
<select> <option></option> <option></option> <option></option> <option></option> </select>
Ce code montre que nous prévoyons de décrire une zone de liste déroulante contenant quatre éléments.
La
<select>
et ses balises
<option>
ont un attribut
value
. Cependant, ces attributs ont des significations différentes. La valeur
value
affectée à l'élément
<option>
indique quelle devrait être la propriété d'état correspondante lorsque cet élément est sélectionné. Ce sont les lignes qui devraient figurer dans la liste déroulante. Dans notre cas, il s'agit de certaines destinations, par exemple des pays. Écrivons leurs noms avec une petite lettre afin que leur apparence corresponde aux valeurs des propriétés de
value
des autres éléments du code. Après cela, le code de la zone de liste déroulante ressemblera à ceci:
<select value=> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select>
Si nous parlons de l'attribut
value
de la
<select>
, alors aucune valeur codée en dur ne sera indiquée ici, mais un lien vers la propriété d'état correspondante:
<select value={this.state.destination}> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select>
Attribuez au champ d'autres attributs. En particulier, le nom correspondant au nom de la propriété dans l'état et le
onChange
événements
this.handleChange
,
this.handleChange
.
<select value={this.state.destination} name="destination" onChange={this.handleChange} > <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select>
Nous allons maintenant configurer la description de l'élément
<p>
, qui affichera ce qui est sélectionné dans le champ de
destination
:
<p>Your destination: {this.state.destination}</p>
Si vous regardez la page dans le navigateur en ce moment, vous pouvez voir que le premier élément de la liste est automatiquement sélectionné dans le champ, mais cela ne conduit évidemment pas à une mise à jour de l'état, car rien ne s'affiche après les deux-points dans la ligne
Your destination:
:.
Application dans le navigateurPour que la valeur de l'
germany
tombe dans l'état, vous devez ouvrir la zone de liste déroulante et sélectionner d'abord autre chose, puis sélectionner
Germany
.
Souvent, afin de prendre en compte cette caractéristique des champs de liste, dans leurs listes, en tant que premier élément, ils mettent quelque chose comme un élément avec une valeur vide et avec du texte comme
-- Please Choose a destination --
. Dans notre cas, cela peut ressembler à ceci:
<select value={this.state.destination} name="destination" onChange={this.handleChange} > <option value="">-- Please Choose a destination --</option> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select>
Nous nous concentrerons sur cette option de configuration de la zone de liste déroulante.
Voyons maintenant, peut-être, la partie la plus difficile de notre tâche, qui est associée aux drapeaux. Ici, il convient d'
dietaryRestrictions
que la propriété d'état
dietaryRestrictions
, qui devrait être utilisée pour fonctionner avec des indicateurs, a été initialisée avec un tableau vide. Maintenant, quand il s'agit de travailler avec des contrôles, on a le sentiment qu'il vaudrait mieux représenter ce champ comme un objet. Il sera donc plus pratique de travailler avec des entités qui représentent des indicateurs individuels sous la forme de propriétés de cet objet avec des noms conviviaux, et non sous la forme d'éléments de tableau. Les propriétés de l'objet, qui seront désormais représentées par la
dietaryRestrictions
état
dietaryRestrictions
, contiendront des valeurs booléennes indiquant si la case à cocher correspondante est désactivée (
false
) ou cochée (
true
). Maintenant, le code d'initialisation d'état ressemblera à ceci:
this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", dietaryRestrictions: { isVegan: false, isKosher: false, isLactoseFree: false } }
Comme vous pouvez le voir, nous prévoyons de créer trois drapeaux. Tous, immédiatement après le chargement de la page, seront réinitialisés.
Nous décrivons les drapeaux dans le code renvoyé par le composant, en les enveloppant dans des balises
<label>
et en définissant leurs attributs. Voici à quoi ressemblera leur code:
<label> <input type="checkbox" name="isVegan" onChange={this.handleChange} checked={this.state.dietaryRestrictions.isVegan} /> Vegan? </label> <br /> <label> <input type="checkbox" name="isKosher" onChange={this.handleChange} checked={this.state.dietaryRestrictions.isKosher} /> Kosher? </label> <br /> <label> <input type="checkbox" name="isLactoseFree" onChange={this.handleChange} checked={this.state.dietaryRestrictions.isLactoseFree} /> Lactose Free? </label>
Les noms des propriétés de l'objet
dietaryRestrictions
ont été utilisés comme noms d'indicateur et les constructions de la forme
this.state.dietaryRestrictions.isSomething
comme valeurs de leurs attributs
checked
.
Veuillez noter que bien que le
onChange
déjà existant soit indiqué comme un gestionnaire d'événement
this.handleChange
onChange, nous devons apporter quelques modifications au programme pour nous assurer que le programme fonctionne correctement.
Jetez un œil à l'application.
Application dans le navigateurComme vous pouvez le voir, les drapeaux sur la page sont affichés, mais le composant ne contient pas encore tous les mécanismes nécessaires pour assurer leur bon fonctionnement. Voyons le gestionnaire d'événements.
Ici, pour travailler avec des cases à cocher, nous devons extraire
event.target
de l'objet, en plus de ceux déjà extraits, du
type
et des propriétés
checked
. Le premier est nécessaire pour vérifier le type de l'élément (les drapeaux sont du type représenté par la ligne de
checkbox
), le second est de savoir si la case à cocher est cochée ou décochée. S'il s'avère que le gestionnaire a été appelé après que l'utilisateur a interagi avec l'indicateur, nous utilisons une procédure de définition d'état spéciale. Nous traiterons les événements des autres contrôles de la même manière qu'auparavant.
Lors de la mise à jour d'un état, il convient de garder à l'esprit que React est un système assez intelligent qui, si seulement une partie de l'état est mis à jour, combinera automatiquement dans le nouvel état ce qui est resté inchangé avec ce qui a changé. Mais on ne peut pas être sûr que le travail avec les propriétés des objets, qui sont les valeurs des propriétés d'état, sera effectué de la même manière. Nous allons vérifier cela en apportant le code
handleChange
au formulaire suivant. Ici, nous partons de l'hypothèse que les propriétés de l'objet
dietaryRestrictions
peuvent être modifiées une par une:
handleChange(event) { const {name, value, type, checked} = event.target type === "checkbox" ? this.setState({ dietaryRestrictions: { [name]: checked } }) : this.setState({ [name]: value }) }
Si vous ouvrez la page d'application dans un navigateur, puis immédiatement après l'avoir téléchargée, tout ira bien, lorsque vous essayez, par exemple, d'entrer un nom dans le champ
First Name
, tout fonctionnera également comme avant, mais lorsque vous essayez de définir l'une des cases à cocher, l'avertissement suivant sera émis :
Avertissement: Un composant modifie une case à cocher d'entrée contrôlée de type pour être non contrôlé. Les éléments d'entrée ne doivent pas passer de contrôlés à non contrôlés (ou vice versa). Décidez entre l'utilisation d'un élément d'entrée contrôlé ou non contrôlé pendant la durée de vie du composant. Plus d'informations: fb.me/react-controlled-components
Afin de mettre à jour correctement le contenu de l'objet
dietaryRestrictions
, vous pouvez utiliser le
setState
fonctionnel
setState
pour créer vous-même une nouvelle version de l'état. Si nous devions gérer un grand nombre de drapeaux, nous l'aurions probablement fait. Mais ici, nous ferons autrement. À savoir, nous allons créer les propriétés d'
dietaryRestrictions
objet
dietaryRestrictions
, en nous débarrassant de cet objet:
this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", isVegan: false, isKosher: false, isLactoseFree: false }
Nous allons maintenant modifier les paramètres des attributs des drapeaux, en
dietaryRestrictions
:
<label> <input type="checkbox" name="isVegan" onChange={this.handleChange} checked={this.state.isVegan} /> Vegan? </label> <br /> <label> <input type="checkbox" name="isKosher" onChange={this.handleChange} checked={this.state.isKosher} /> Kosher? </label> <br /> <label> <input type="checkbox" name="isLactoseFree" onChange={this.handleChange} checked={this.state.isLactoseFree} /> Lactose Free? </label>
Et enfin, éditez le code de l'élément qui affiche des informations sur les restrictions alimentaires spécifiées par l'utilisateur:
<p>Your dietary restrictions:</p> <p>Vegan: {this.state.isVegan ? "Yes" : "No"}</p> <p>Kosher: {this.state.isKosher ? "Yes" : "No"}</p> <p>Lactose Free: {this.state.isLactoseFree ? "Yes" : "No"}</p>
Après cela, nous vérifierons l'intégrité de l'application.
Application dans le navigateurComme vous pouvez le voir, tout fonctionne comme prévu.
Voici le code complet du composant
App
:
import React, {Component} from "react" class App extends Component { constructor() { super() this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", isVegan: false, isKosher: false, isLactoseFree: false } this.handleChange = this.handleChange.bind(this) } handleChange(event) { const {name, value, type, checked} = event.target type === "checkbox" ? this.setState({ [name]: checked }) : this.setState({ [name]: value }) } render() { return ( <main> <form> <input name="firstName" value={this.state.firstName} onChange={this.handleChange} placeholder="First Name" /> <br /> <input name="lastName" value={this.state.lastName} onChange={this.handleChange} placeholder="Last Name" /> <br /> <input name="age" value={this.state.age} onChange={this.handleChange} placeholder="Age" /> <br /> <label> <input type="radio" name="gender" value="male" checked={this.state.gender === "male"} onChange={this.handleChange} /> Male </label> <br /> <label> <input type="radio" name="gender" value="female" checked={this.state.gender === "female"} onChange={this.handleChange} /> Female </label> <br /> <select value={this.state.destination} name="destination" onChange={this.handleChange} > <option value="">-- Please Choose a destination --</option> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select> <br /> <label> <input type="checkbox" name="isVegan" onChange={this.handleChange} checked={this.state.isVegan} /> Vegan? </label> <br /> <label> <input type="checkbox" name="isKosher" onChange={this.handleChange} checked={this.state.isKosher} /> Kosher? </label> <br /> <label> <input type="checkbox" name="isLactoseFree" onChange={this.handleChange} checked={this.state.isLactoseFree} /> Lactose Free? </label> <br /> <button>Submit</button> </form> <hr /> <h2><font color="#3AC1EF">Entered information:</font></h2> <p>Your name: {this.state.firstName} {this.state.lastName}</p> <p>Your age: {this.state.age}</p> <p>Your gender: {this.state.gender}</p> <p>Your destination: {this.state.destination}</p> <p>Your dietary restrictions:</p> <p>Vegan: {this.state.isVegan ? "Yes" : "No"}</p> <p>Kosher: {this.state.isKosher ? "Yes" : "No"}</p> <p>Lactose Free: {this.state.isLactoseFree ? "Yes" : "No"}</p> </main> ) } } export default App
Résumé
Aujourd'hui, vous avez terminé les travaux pratiques sur les formulaires. Ensuite, vous avez répété ce que vous avez appris dans les cours précédents, et nous espérons que vous avez appris quelque chose de nouveau. La prochaine fois, nous parlerons de l'architecture des applications React.
Chers lecteurs! Dites-moi, a-t-il été difficile de terminer ce travail pratique?
