React Tutorial Teil 25: Workshop zu Formularen

Im heutigen Teil der Übersetzung des React-Schulungskurses sind Sie eingeladen, eine Formularaufgabe zu erledigen.

Bild

Teil 1: Kursübersicht, Gründe für die Beliebtheit von React, ReactDOM und JSX
Teil 2: Funktionskomponenten
Teil 3: Komponentendateien, Projektstruktur
Teil 4: übergeordnete und untergeordnete Komponenten
Teil 5: Beginn der Arbeit an einer TODO-Anwendung, Grundlagen des Stylings
Teil 6: Über einige Funktionen des Kurses, JSX und JavaScript
Teil 7: Inline-Stile
Teil 8: Fortsetzung der Arbeit an der TODO-Anwendung, Vertrautheit mit den Eigenschaften von Komponenten
Teil 9: Komponenteneigenschaften
Teil 10: Workshop zum Arbeiten mit Komponenteneigenschaften und Styling
Teil 11: Dynamische Markup-Generierung und Map-Arrays-Methode
Teil 12: Workshop, dritte Phase der Arbeit an einer TODO-Anwendung
Teil 13: Klassenbasierte Komponenten
Teil 14: Workshop zu klassenbasierten Komponenten, Komponentenstatus
Teil 15: Komponentengesundheitsworkshops
Teil 16: Die vierte Phase der Arbeit an einer TODO-Anwendung, die Ereignisbehandlung
Teil 17: Fünfte Phase der Arbeit an einer TODO-Anwendung, Änderung des Status von Komponenten
Teil 18: Die sechste Phase der Arbeit an einer TODO-Anwendung
Teil 19: Methoden des Komponentenlebenszyklus
Teil 20: Die erste Lektion in bedingtem Rendern
Teil 21: Zweite Lektion und Workshop zum bedingten Rendern
Teil 22: Die siebte Phase der Arbeit an einer TODO-Anwendung, bei der Daten aus externen Quellen heruntergeladen werden
Teil 23: Erste Lektion zum Arbeiten mit Formularen
Teil 24: Lektion der zweiten Form
Teil 25: Workshop zum Arbeiten mit Formularen
Teil 26: Anwendungsarchitektur, Container- / Komponentenmuster
Teil 27: Kursprojekt

Lektion 43. Workshop. Mit Formularen arbeiten


Original

»Job


In dieser praktischen Lektion werden Sie aufgefordert, den Code der App Komponente App.js , der sich in der Datei App.js des von create-react-app erstellten Standardprojekts befindet. Hier ist der 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 

Im Allgemeinen müssen Sie sicherstellen, dass die Daten, die der Benutzer während der Arbeit mit den Formularsteuerelementen eingibt, sofort im Text unter diesem Formular angezeigt werden. Nutzen Sie die verwaltete Komponententechnologie , wenn Sie die Aufgabe erledigen. Es ist zu beachten, dass die Ihnen angebotene Aufgabe eine angepasste Version dieser Aufgabe ist, sodass Sie sie sich ansehen können, um die Funktionen der Steuerelemente, die Sie erstellen und konfigurieren sollen, besser zu verstehen.

Hier ist, was die Komponente jetzt auf dem Bildschirm anzeigt.


Anwendung im Browser

▍Lösung


Sie können sich der Lösung des Ihnen vorgeschlagenen Problems von verschiedenen Seiten nähern. Wir beginnen damit, alles, was wir brauchen, in den Zustand zu versetzen, wonach wir die Kontrollen und andere Mechanismen der Komponente einrichten.

Im Moment sieht der Status der Komponente wie unten gezeigt aus.

 this.state = {   firstName: "",   lastName: "",   age: 0,   gender: "",   destination: "",   dietaryRestrictions: [] } 

Es sollte bedacht werden, dass sich bei der Arbeit an einem Programm möglicherweise herausstellt, dass es beispielsweise bequemer ist, einen Zustand anders zu initialisieren. Wenn wir auf etwas Ähnliches stoßen, ändern wir den Statusinitialisierungscode. Insbesondere können jetzt einige Zweifel durch die in die Eigenschaft age geschriebene Zahl 0 verursacht werden, in der das vom Benutzer eingegebene Alter gespeichert werden soll. Möglicherweise muss das Flag-Datenspeichersystem, das jetzt durch die Eigenschaft dietaryRestrictions , die durch ein leeres Array initialisiert wird, etwas anderes tun.

Lassen Sie uns nun nach der Initialisierung des Status die Einstellungen vornehmen. Da der Code bereits eine Beschreibung der Eingabefelder enthält, beginnen wir mit ihnen.

Diese Steuerelemente müssen benannt werden, indem ihre Namensattribute so festgelegt werden, dass sie mit den Namen der Statuseigenschaften übereinstimmen, in denen die in diese Felder eingegebenen Daten gespeichert werden. Sie sollten ein value , dessen Wert basierend auf den im Status gespeicherten Daten bestimmt wird. Wenn Sie Daten in jedes dieser Felder onChange , müssen Sie die eingegebenen Daten an die Komponente übergeben, was dazu führt, dass sie über einen onChange Ereignishandler verfügen onChange . All diese Überlegungen führen dazu, dass die Beschreibung der Felder nun so aussieht:

 <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" /> 

this.handleChange ist als Methode zur Verarbeitung der onChange Ereignisse dieser Felder noch nicht vorhanden. Erstellen Sie diese Methode:

 handleChange(event) {   const {name, value} = event.target   this.setState({       [name]: value   }) } 

Hier extrahieren wir die name und Werteigenschaften aus dem event.target Objekt und verwenden sie dann, um die entsprechende event.target . Im Moment wird ein solcher universeller Ereignishandlercode zu uns passen, aber später, wenn wir mit Flags arbeiten, werden wir Änderungen daran vornehmen.

Vergessen Sie nicht, dass this Bindung im Komponentenkonstruktor ausgeführt wird:

 this.handleChange = this.handleChange.bind(this) 

Um eine Ausgabe am Ende der Seite der Daten zu erreichen, die in die Felder firstName , secondName und age firstName , secondName wir mit den entsprechenden <p> -Elementen und bringen sie in die folgende Form:

 <p>Your name: {this.state.firstName} {this.state.lastName}</p> <p>Your age: {this.state.age}</p> 

Schauen wir uns jetzt an, was wir haben.


Anwendung im Browser

Wie Sie sehen können, wird im Feld zur Eingabe des Alters kein Hinweis angezeigt. Stattdessen wird angezeigt, was in der Eigenschaft state of age ist, dh 0. Wir benötigen einen Hinweis im leeren Feld. Versuchen wir, den Wert des age im Status durch null zu ersetzen. Danach stellt sich heraus, dass das Formular so aussieht, wie es sollte, aber in der Konsole wird die folgende Warnung bezüglich des Altersfelds angezeigt:

 Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components 

Infolgedessen müssen wir den Wert der Eigenschaft age state durch eine leere Zeichenfolge ersetzen und den Statusinitialisierungscode in die folgende Form bringen:

 this.state = {   firstName: "",   lastName: "",   age: "",   gender: "",   destination: "",   dietaryRestrictions: [] } 

Probieren Sie jetzt das Formular aus. Unmittelbar nach der Eröffnung sieht es genauso aus wie zu Beginn der Arbeit, dh die Eingabeaufforderung kehrt zum age zurück. Beim Ausfüllen der Felder werden die eingegebenen Daten unten auf der Seite angezeigt.


Anwendung im Browser

Wie Sie sehen, funktioniert in dieser Phase der Arbeit alles wie erwartet.

Jetzt werden wir uns mit neuen Elementen beschäftigen. Der nächste Schritt bei der Bearbeitung des Formulars ist das Hinzufügen von Schaltern.

Wickeln Sie die Schalter in das <label> , damit wir nicht nur den Schalter signieren, sondern auch sicherstellen können, dass das Klicken auf diese Signatur, dh auf das übergeordnete Element, zur Auswahl führt.

Wenn Sie mit Switches arbeiten, sollten Sie bedenken, dass es sich um eine Kombination von Flags mit dem checked Attribut und Textfeldern mit dem checked . Die Switches bilden eine Gruppe, in der jedem der Switches derselbe Name zugewiesen wird, und die checked Eigenschaft der Switches wird gemäß einer Bedingung festgelegt, die so konfiguriert ist, dass es unmöglich ist, mehr als einen Switch einzuschalten, der Teil derselben Gruppe ist. onChange als Ereignishandler für die onChange Switches fest.

Infolgedessen sieht der Schalterbeschreibungscode folgendermaßen aus:

 <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> 

Jetzt verarbeiten wir das entsprechende <p> -Element am Ende der Seite wie folgt:

 <p>Your gender: {this.state.gender}</p> 

Danach kann das Formular getestet werden. Unmittelbar nach dem Start werden beide Schalter nicht ausgewählt, da ein Status in einem Wert gespeichert ist, bei dem keine der beim Festlegen ihrer checked Eigenschaft durchgeführten checked true . Nachdem Sie auf einen von ihnen geklickt haben, fällt der entsprechende Wert in den Status (gespeichert im Wertattribut des Schalters), der Schalter wird ausgewählt und der entsprechende Text wird am unteren Rand des Formulars angezeigt.


Anwendung im Browser

Lassen Sie uns nun am Kombinationsfeld arbeiten. Sein Werkstück sieht so aus:

 <select>   <option></option>   <option></option>   <option></option>   <option></option> </select> 

Dieser Code zeigt, dass wir ein Kombinationsfeld mit vier Elementen beschreiben möchten.

Das <select> -Tag und seine <option> -Tags haben ein Wertattribut. Diese Attribute haben jedoch unterschiedliche Bedeutungen. Der dem <option> -Element zugewiesene value gibt an, wie die entsprechende Statuseigenschaft aussehen soll, wenn dieses Element ausgewählt wird. Dies sind die Zeilen, die in der Dropdown-Liste enthalten sein sollten. In unserem Fall sind dies bestimmte Ziele, beispielsweise Länder. Schreiben wir ihre Namen mit einem kleinen Buchstaben, damit ihr Aussehen den Werten der Werteigenschaften anderer Elemente im Code entspricht. Danach sieht der Code für das Kombinationsfeld folgendermaßen aus:

 <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> 

Wenn wir über das value Attribut des <select> sprechen, wird hier kein fest codierter Wert angezeigt, sondern ein Link zur entsprechenden state-Eigenschaft:

 <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> 

Weisen Sie dem Feld andere Attribute zu. Insbesondere der Name, der dem Namen der Eigenschaft im Status entspricht, und der onChange Ereignishandler 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> 

Jetzt konfigurieren wir die Beschreibung des <p> -Elements, das anzeigt, was im destination ausgewählt destination :

 <p>Your destination: {this.state.destination}</p> 

Wenn Sie sich jetzt die Seite im Browser ansehen, können Sie sehen, dass das erste Element der Liste automatisch im Feld ausgewählt wird. Dies führt jedoch offensichtlich nicht zu einer Aktualisierung des Status, da nach dem Doppelpunkt in der Zeile Your destination: nichts angezeigt wird.


Anwendung im Browser

Damit der deutsche Wert in den Status fällt, müssen Sie das Kombinationsfeld öffnen und zuerst etwas anderes und dann Germany auswählen.

Um diese Funktion von Listenfeldern in ihren Listen als erstes Element zu berücksichtigen, setzen sie häufig so etwas wie ein Element mit einem leeren Wert und einem Text wie " -- Please Choose a destination -- . In unserem Fall könnte es so aussehen:

 <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> 

Wir werden uns auf diese Option zum Einstellen des Kombinationsfelds konzentrieren.

Lassen Sie uns nun den vielleicht schwierigsten Teil unserer Aufgabe behandeln, der mit Flaggen verbunden ist. Hier ist zu dietaryRestrictions dass die staatliche Eigenschaft dietaryRestrictions , die für die Arbeit mit Flags verwendet werden soll, mit einem leeren Array initialisiert wurde. Wenn es um die Arbeit mit Steuerelementen geht, besteht das Gefühl, dass es besser ist, dieses Feld als Objekt darzustellen. Daher ist es bequemer, mit Entitäten zu arbeiten, die einzelne Flags in Form von Eigenschaften dieses Objekts mit Anzeigenamen und nicht in Form von Array-Elementen darstellen. Die Eigenschaften des Objekts, die jetzt durch die dietaryRestrictions state dargestellt werden, enthalten boolesche Werte, die angeben, ob das entsprechende Kontrollkästchen dietaryRestrictions ( false ) oder aktiviert ( true ) ist. Der Statusinitialisierungscode sieht nun folgendermaßen aus:

 this.state = {   firstName: "",   lastName: "",   age: "",   gender: "",   destination: "",   dietaryRestrictions: {       isVegan: false,       isKosher: false,       isLactoseFree: false   } } 

Wie Sie sehen können, planen wir die Erstellung von drei Flags. Alle werden unmittelbar nach dem Laden der Seite zurückgesetzt.

Wir beschreiben die Flags in dem von der Komponente zurückgegebenen Code, wickeln sie in <label> -Tags ein und legen ihre Attribute fest. So wird ihr Code aussehen:

 <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> 

Die Namen der verwendeten Flags sind Eigenschaftsnamen des dietaryRestrictions Objekts, und die Werte ihrer checked Attribute sind Konstruktionen der Form this.state.dietaryRestrictions.isSomething .

Bitte beachten Sie, dass der bereits vorhandene onChange zwar als this.handleChange Ereignishandler angezeigt wird, wir jedoch einige Änderungen am Programm vornehmen müssen, um sicherzustellen, dass das Programm ordnungsgemäß funktioniert.

Schauen Sie sich die Anwendung an.


Anwendung im Browser

Wie Sie sehen können, werden die Flags auf der Seite angezeigt, aber die Komponente enthält noch nicht alle Mechanismen, die für den ordnungsgemäßen Betrieb erforderlich sind. Beschäftigen wir uns mit dem Event-Handler.

event.target mit Kontrollkästchen arbeiten zu können, müssen wir event.target aus dem Objekt extrahieren, zusätzlich zu den bereits extrahierten, dem type und den checked Eigenschaften. Das erste wird benötigt, um den Typ des Elements zu überprüfen (die Flags sind vom Typ, der durch die checkbox wird), das zweite, um herauszufinden, ob das Kontrollkästchen aktiviert oder deaktiviert ist. Wenn sich herausstellt, dass der Handler aufgerufen wurde, nachdem der Benutzer mit dem Flag interagiert hat, verwenden wir ein spezielles Statuseinstellungsverfahren. Wir werden die Ereignisse anderer Steuerelemente auf die gleiche Weise wie zuvor behandeln.

Bei der Aktualisierung eines Status sollte berücksichtigt werden, dass React ein ziemlich intelligentes System ist, das, wenn nur ein Teil des Status aktualisiert wird, automatisch im neuen Status kombiniert, was unverändert geblieben ist, mit dem, was sich geändert hat. Man kann jedoch nicht sicher sein, dass die Arbeit mit den Eigenschaften von Objekten, die die Werte von Zustandseigenschaften sind, auf die gleiche Weise ausgeführt wird. Wir werden dies überprüfen, indem wir den handleChange Code in das folgende Formular bringen. Hier gehen wir von der Annahme aus, dass die Eigenschaften des Objekts dietaryRestrictions einzeln geändert werden können:

 handleChange(event) {   const {name, value, type, checked} = event.target   type === "checkbox" ?       this.setState({           dietaryRestrictions: {               [name]: checked           }       })   :   this.setState({       [name]: value   }) } 

Wenn Sie die Anwendungsseite in einem Browser öffnen, sieht sofort nach dem Herunterladen alles gut aus. Wenn Sie beispielsweise versuchen, einen Namen in das Feld First Name einzugeben, funktioniert alles wie zuvor. Wenn Sie jedoch versuchen, eines der Kontrollkästchen zu aktivieren, wird die folgende Warnung ausgegeben ::
Warnung: Eine Komponente ändert ein Kontrollkästchen für eine kontrollierte Eingabe vom Typ so, dass sie nicht mehr gesteuert wird. Eingabeelemente sollten nicht von gesteuert zu unkontrolliert (oder umgekehrt) wechseln. Entscheiden Sie sich für die Lebensdauer der Komponente zwischen der Verwendung eines gesteuerten oder unkontrollierten Eingabeelements. Weitere Informationen: fb.me/react-controlled-components

Um den Inhalt des dietaryRestrictions Objekts korrekt zu aktualisieren, können Sie mit dem Funktionsformular setState selbst eine neue Version des Status erstellen. Wenn wir eine große Anzahl von Flags verwalten müssten, hätten wir dies wahrscheinlich getan. Aber hier werden wir es anders machen. Wir werden nämlich die Eigenschaften der dietaryRestrictions von dietaryRestrictions dieses Objekt dietaryRestrictions :

 this.state = {   firstName: "",   lastName: "",   age: "",   gender: "",   destination: "",   isVegan: false,   isKosher: false,   isLactoseFree: false } 

Jetzt ändern wir die Einstellungen für die Attribute der Flags, um 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> 

Bearbeiten Sie abschließend den Code des Elements, in dem Informationen zu den vom Benutzer angegebenen Ernährungseinschränkungen angezeigt werden:

 <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> 

Danach überprüfen wir den Zustand der Anwendung.


Anwendung im Browser

Wie Sie sehen, funktioniert alles wie erwartet.

Hier ist der vollständige Code der App Komponente:

 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 

Zusammenfassung


Heute haben Sie die praktische Arbeit an den Formularen abgeschlossen. Dann haben Sie wiederholt, was Sie in früheren Kursen gelernt haben, und wir hoffen, Sie haben etwas Neues gelernt. Nächstes Mal werden wir über die Architektur von React-Anwendungen sprechen.

Liebe Leser! Sag mir, war es schwierig, diese praktische Arbeit abzuschließen?

Source: https://habr.com/ru/post/de446208/


All Articles