Reaktionsschulung Teil 27: Kursprojekt

In diesem Teil der Ăśbersetzung des React-Schulungskurses werden Sie aufgefordert, einen Meme-Generator zu erstellen.

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 45. Kursprojekt. Meme Generator


→ Original

Also kamen wir zum Kursprojekt. Erstellen wir eine Anwendung, die Memes generiert. Beginnen wir mit dem Standardprojekt create-react-app, das mit diesem Befehl erstellt wurde:

npx create-react-app meme-generator 

Hier finden Sie Informationen zu den Verwendungsmöglichkeiten.

Während der Arbeit an diesem Projekt werden Sie gebeten, einige seiner Teile selbst zu implementieren und dann die Erläuterungen dazu zu lesen. Das Standardprojekt verfügt bereits über Boilerplate-Code, insbesondere in den App.js index.js und App.js Sie können diesen Code vollständig entfernen und versuchen, ihn selbst zu schreiben, um sich in der Implementierung der Standardmechanismen von React-Anwendungen zu testen.

In diesem Projekt sind Sie eingeladen, die folgenden Stile zu verwenden:

 * {   box-sizing: border-box; } body {   margin: 0;   background-color: whitesmoke; } header {   height: 100px;   display: flex;   align-items: center;   background: #6441A5;  /* fallback for old browsers */   background: -webkit-linear-gradient(to right, #2a0845, #6441A5);  /* Chrome 10-25, Safari 5.1-6 */   background: linear-gradient(to right, #2a0845, #6441A5); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ } header > img {   height: 80%;   margin-left: 10%; } header > p {   font-family: VT323, monospace;   color: whitesmoke;   font-size: 50px;   margin-left: 60px; } .meme {   position: relative;   width: 90%;   margin: auto; } .meme > img {   width: 100%; } .meme > h2 {   position: absolute;   width: 80%;   text-align: center;   left: 50%;   transform: translateX(-50%);   margin: 15px 0;   padding: 0 5px;   font-family: impact, sans-serif;   font-size: 2em;   text-transform: uppercase;   color: white;   letter-spacing: 1px;   text-shadow:       2px 2px 0 #000,       -2px -2px 0 #000,       2px -2px 0 #000,       -2px 2px 0 #000,       0 2px 0 #000,       2px 0 0 #000,       0 -2px 0 #000,       -2px 0 0 #000,       2px 2px 5px #000; } .meme > .bottom {   bottom: 0; } .meme > .top {   top: 0; } .meme-form {   width: 90%;   margin: 20px auto;   display: flex;   justify-content: space-between; } .meme-form > input {   width: 45%;   height: 40px; } .meme-form > button {   border: none;   font-family: VT323, monospace;   font-size: 25px;   letter-spacing: 1.5px;   color: white;   background: #6441A5; } .meme-form > input::-webkit-input-placeholder { /* Chrome/Opera/Safari */ font-family: VT323, monospace; font-size: 25px; text-align: cen } .meme-form > input::-moz-placeholder { /* Firefox 19+ */ font-family: VT323, monospace; font-size: 25px; text-align: cen } .meme-form > input:-ms-input-placeholder { /* IE 10+ */ font-family: VT323, monospace; font-size: 25px; text-align: cen } .meme-form > input:-moz-placeholder { /* Firefox 18- */ font-family: VT323, monospace; font-size: 25px; text-align: cen } 

Diese Stile können in der Datei index.css enthalten sein, die sich bereits im Projekt befindet, und in der Datei index.js enthalten sein.

index.js von der Annahme, dass die Dateien index.js und App.js jetzt leer sind, werden Sie als erste Aufgabe aufgefordert, den Code index.js zu schreiben, die einfachste Komponente in App.js und in App.js index.js .

index.js sollte in index.js :

 import React from "react" import ReactDOM from "react-dom" import './index.css' import App from "./App" ReactDOM.render(<App />, document.getElementById("root")) 

Hier importieren wir React und ReactDOM , importieren Stile aus index.css und der App Komponente. AnschlieĂźend ReactDOM.render() wir mithilfe der ReactDOM.render() -Methode das, was die App Komponente bildet, in das Element der index.html Seite mit der root <div id="root"></div> ( <div id="root"></div> ).

So könnte die App.js Datei aussehen:

 import React from "react" function App() {   return (       <h1>Hello world!</h1>   ) } export default App 

Hier wird nun die einfachste Funktionskomponente vorgestellt.

Zu diesem Zeitpunkt sieht das Projekt wie das unten gezeigte aus.


Anwendung im Browser

Erstellen Sie nun zwei neue Komponenten in zwei Dateien, deren Namen den Namen der Komponenten entsprechen:

  • Die Header Komponente, mit der der Anwendungsheader angezeigt wird.
  • Die MemeGenerator Komponente, in der die der Anwendung zugewiesenen Hauptaufgaben gelöst werden. Hier werden nämlich Aufrufe der API ausgefĂĽhrt. Anwendungsdaten werden hier gespeichert.

Ăśberlegen Sie sich, welche Funktionen diesen Komponenten zugewiesen sind.

Hier ist der Inhalt der Datei Header.js :

 import React from "react" function Header() {   return (       <h1>HEADER</h1>   ) } export default Header 

Da diese Komponente nur zur Anzeige des Anwendungsheaders verwendet wird, haben wir sie als Funktionskomponente konzipiert.

Hier ist der Code fĂĽr die Datei MemeGenerator.js :

 import React, {Component} from "react" class MemeGenerator extends Component {   constructor() {       super()       this.state ={}   }     render() {       return (           <h1>MEME GENERATOR SECTION</h1>       )   } } export default MemeGenerator 

Unter Berücksichtigung der Aufgaben, die mit der MemeGenerator Komponente gelöst werden sollen, verwenden wir hier eine Komponente, die auf der Klasse basiert. Hier gibt es einen Konstruktor, in dem wir den Zustand mit einem leeren Objekt initialisieren.

Nachdem wir diese Dateien erstellt haben, importieren wir sie in App.js und geben das Markup von der Funktionskomponente der App , die Instanzen dieser Komponenten verwendet. Dabei ist nicht zu vergessen, dass die Funktionskomponente, wenn sie mehrere Elemente zurĂĽckgibt, in etwas eingeschlossen werden muss. In unserem Fall ist dies das <div> . Hier ist der aktualisierte App.js Code:

 import React from "react" import Header from "./Header" import MemeGenerator from "./MemeGenerator" function App() {   return (       <div>           <Header />           <MemeGenerator />       </div>   ) } export default App 

ĂśberprĂĽfen Sie das Erscheinungsbild der Anwendung.


Anwendung im Browser

Lassen Sie uns nun an der Header Komponente arbeiten. Hier verwenden wir das semantische Element HTML5 <header> . Dieses Tag enthält das Bild und den Text. Nun Header.js der Code der Datei Header.js aus:

 import React from "react" function Header() {   return (       <header>           <img               src="http://www.pngall.com/wp-content/uploads/2016/05/Trollface.png"               alt="Problem?"           />           <p>Meme Generator</p>       </header>   ) } export default Header 

So ändert sich das Aussehen der App.


Anwendung im Browser

Der Titel der Anwendung entspricht den zuvor in index.js . Die Arbeit an der Header Komponente ist nun abgeschlossen.

Beschäftigen MemeGenerator weiterhin mit der MemeGenerator Komponente. Jetzt können Sie den Status dieser Komponente unabhängig initialisieren, indem Sie die folgenden Daten darauf schreiben:

  • Der Text, der oben im Mem angezeigt wird (Eigenschaft topText ).
  • Der am unteren Rand des Memes angezeigte Text (Eigenschaft bottomText ).
  • Zufälliges Bild ( randomImage Eigenschaft, die mit dem Link http://i.imgflip.com/1bij.jpg initialisiert werden muss).

Dies ist der Code von MemeGenerator.js nach der Initialisierung des Status:

 import React, {Component} from "react" class MemeGenerator extends Component {   constructor() {       super()       this.state = {           topText: "",           bottomText: "",           randomImg: "http://i.imgflip.com/1bij.jpg"       }   }     render() {       return (           <h1>MEME GENERATOR SECTION</h1>       )   } } export default MemeGenerator 

Jetzt wird das Erscheinungsbild der Anwendung nicht beeinflusst.

Wir werden Aufrufe an die API verwenden, die ein Array von Objekten zurückgibt, die Links zu Bildern enthalten, auf deren Grundlage Memes erstellt werden können. In dieser Phase der Projektarbeit werden Sie aufgefordert, die folgenden Funktionen in der MemeGenerator Komponente zu implementieren:


Hier wird zur Verdeutlichung ein Fragment der JSON-Daten beim Zugriff auf diese API zurĂĽckgegeben:

 {   "success":true,  "data":{      "memes":[         {           "id":"112126428",           "name":"Distracted Boyfriend",           "url":"https:\/\/i.imgflip.com\/1ur9b0.jpg",           "width":1200,           "height":800,           "box_count":3        },        {           "id":"87743020",           "name":"Two Buttons",           "url":"https:\/\/i.imgflip.com\/1g8my4.jpg",           "width":600,           "height":908,           "box_count":2        },        {           "id":"129242436",           "name":"Change My Mind",           "url":"https:\/\/i.imgflip.com\/24y43o.jpg",           "width":482,           "height":361,           "box_count":2        },        ….  ]  } } 

Um das oben gestellte Problem zu lösen, muss berücksichtigt werden, dass es sich um die Daten handelt, die die Komponente zu Beginn der Anwendung benötigt.

Um sie zu laden, greifen wir daher auf die componentDidMount() . Hier rufen wir mit der Standardmethode fetch() die API auf. Es gibt ein Versprechen zurĂĽck. Nach dem Laden der Daten steht uns das allMemeImgs zur VerfĂĽgung. Wir extrahieren das memes Array daraus und allMemeImgs es in die neue allMemeImgs , die mit einem leeren Array initialisiert wurde. Da diese Daten noch nicht verwendet werden, um etwas zu bilden, das auf dem Bildschirm angezeigt wird, drucken wir das erste Element des Arrays auf die Konsole, um die korrekte Funktion des Datenlademechanismus zu ĂĽberprĂĽfen.

Hier ist der Code der MemeGenerator Komponente in dieser Arbeitsphase:

 import React, {Component} from "react" class MemeGenerator extends Component {   constructor() {       super()       this.state = {           topText: "",           bottomText: "",           randomImg: "http://i.imgflip.com/1bij.jpg",           allMemeImgs: []       }   }     componentDidMount() {       fetch("https://api.imgflip.com/get_memes")           .then(response => response.json())           .then(response => {               const {memes} = response.data               console.log(memes[0])               this.setState({ allMemeImgs: memes })           })   }     render() {       return (           <h1>MEME GENERATOR SECTION</h1>       )   } } export default MemeGenerator 

Dies gelangt nach erfolgreichem Laden der Daten zur Konsole.


Anwendung im Browser, Ausgabe an die Konsole des ersten Elements des geladenen Arrays

Beachten Sie, dass das Bild mit vielen Eigenschaften beschrieben wird. Wir verwenden nur die url Eigenschaft, die den Zugriff auf den Link zum Herunterladen des Bildes ermöglicht.

Zu Beginn des Kurses haben wir darĂĽber gesprochen, wie diese Anwendung aussehen wird.


Meme Generator

Die Benutzeroberfläche verfügt insbesondere über einige Felder zur Texteingabe, die im oberen und unteren Teil des Bildes angezeigt werden. Nun sind Sie eingeladen, basierend auf dem unten gezeigten aktualisierten Code der MemeGenerator Komponente, der sich vom obigen Code dieser Komponente dadurch unterscheidet, dass hier ein Formular leer hinzugefügt wird, einige Textfelder, topText und bottomText zu erstellen. Beachten Sie, dass diese Komponenten verwaltet werden müssen. Fügen Sie ihnen die erforderlichen Attribute hinzu. Erstellen Sie einen onChange Ereignishandler onChange diese Felder, in dem Sie die entsprechenden onChange aktualisieren müssen, wenn Sie Text in sie eingeben.

 import React, {Component} from "react" class MemeGenerator extends Component {   constructor() {       super()       this.state = {           topText: "",           bottomText: "",           randomImg: "http://i.imgflip.com/1bij.jpg",           allMemeImgs: []       }   }     componentDidMount() {       fetch("https://api.imgflip.com/get_memes")           .then(response => response.json())           .then(response => {               const {memes} = response.data               this.setState({ allMemeImgs: memes })           })   }     render() {       return (           <div>               <form className="meme-form">                   {                       //                        }                                 <button>Gen</button>               </form>           </div>       )   } } export default MemeGenerator 

Beachten Sie ĂĽbrigens, dass wir einen Kommentar in geschweifte Klammern setzen, um einen Kommentar in den von der render() -Methode zurĂĽckgegebenen Code aufzunehmen, um dem System anzuzeigen, dass dieses Fragment als JavaScript-Code interpretiert werden soll.

Folgendes sollten Sie in dieser Phase der Arbeit an der Anwendung erhalten:

 import React, {Component} from "react" class MemeGenerator extends Component {   constructor() {       super()       this.state = {           topText: "",           bottomText: "",           randomImg: "http://i.imgflip.com/1bij.jpg",           allMemeImgs: []       }       this.handleChange = this.handleChange.bind(this)   }     componentDidMount() {       fetch("https://api.imgflip.com/get_memes")           .then(response => response.json())           .then(response => {               const {memes} = response.data               this.setState({ allMemeImgs: memes })           })   }     handleChange(event) {       const {name, value} = event.target       this.setState({ [name]: value })   }     render() {       return (           <div>               <form className="meme-form">                   <input                       type="text"                       name="topText"                       placeholder="Top Text"                       value={this.state.topText}                       onChange={this.handleChange}                   />                   <input                       type="text"                       name="bottomText"                       placeholder="Bottom Text"                       value={this.state.bottomText}                       onChange={this.handleChange}                   />                                 <button>Gen</button>               </form>           </div>       )   } } export default MemeGenerator 

Jetzt sieht die Anwendungsseite wie unten gezeigt aus.


Anwendung im Browser

Während nur Felder mit Hilfetext angezeigt werden, führt die Eingabe von Daten nicht zu Änderungen in der Benutzeroberfläche. Um den korrekten Betrieb der hier implementierten Mechanismen zu überprüfen, können Sie den Befehl console.log() .

Jetzt arbeiten wir an dem Teil der Anwendung, der für die Anzeige des Bildmems verantwortlich ist. Denken Sie daran, dass wir jetzt ein Array mit Informationen zu Bildern haben, die als Grundlage für Memes dienen sollen. Die Anwendung sollte durch Drücken der Gen Taste zufällig ein Bild aus diesem Array auswählen und ein Mem bilden.

Hier ist der aktualisierte Code für die MemeGenerator Komponente. Hier gibt es in der render() -Methode unterhalb des Formularbeschreibungscodes ein <div> -Element, das ein <img> -Element enthält, das ein Bild anzeigt, und einige <h2> -Elemente, die Beschriftungen anzeigen. Die Elemente <div> und <h2> werden mit Stilen entworfen, die wir dem Projekt zu Beginn der Arbeit hinzugefügt haben.

 import React, {Component} from "react" class MemeGenerator extends Component {   constructor() {       super()       this.state = {           topText: "",           bottomText: "",           randomImg: "http://i.imgflip.com/1bij.jpg",           allMemeImgs: []       }       this.handleChange = this.handleChange.bind(this)   }     componentDidMount() {       fetch("https://api.imgflip.com/get_memes")           .then(response => response.json())           .then(response => {               const {memes} = response.data               this.setState({ allMemeImgs: memes })           })   }     handleChange(event) {       const {name, value} = event.target       this.setState({ [name]: value })   }     render() {       return (           <div>               <form className="meme-form">                   <input                       type="text"                       name="topText"                       placeholder="Top Text"                       value={this.state.topText}                       onChange={this.handleChange}                   />                   <input                       type="text"                       name="bottomText"                       placeholder="Bottom Text"                       value={this.state.bottomText}                       onChange={this.handleChange}                   />                                 <button>Gen</button>               </form>               <div className="meme">                   <img align="center" src={this.state.randomImg} alt="" />                   <h2 className="top">{this.state.topText}</h2>                   <h2 className="bottom">{this.state.bottomText}</h2>               </div>           </div>       )   } } export default MemeGenerator 

So sieht die App jetzt aus.


Anwendung im Browser

Beachten Sie, dass hier das Bild angezeigt wird, das den Status initialisiert hat. Wir verwenden noch keine Bilder, die in der State-Eigenschaft allMemeImgs gespeichert sind. Versuchen wir, etwas in die Textfelder einzugeben.


Anwendung im Browser

Wie Sie sehen können, funktionieren die für die Arbeit mit Text verantwortlichen Anwendungssubsysteme wie erwartet. Jetzt muss nur noch sichergestellt werden, dass durch Drücken der Gen Taste ein zufälliges Bild aus dem Array mit Bilddaten ausgewählt und in das <img> -Element geladen wird, das sich auf der Seite unter den Texteingabefeldern befindet.

Führen Sie die folgende Aufgabe aus, um die Anwendung mit dieser Funktion auszustatten. Erstellen Sie eine Methode, die ausgelöst wird, wenn Sie auf die Schaltfläche Gen klicken. Diese Methode sollte eines der Bilder auswählen, deren Informationen in der state-Eigenschaft allMemeImgs gespeichert allMemeImgs , und dann Aktionen ausführen, mit denen Sie dieses Bild im <img> -Element unter den Texteingabefeldern anzeigen können. allMemeImgs dass allMemeImgs ein Array von Objekten speichert, die Bilder beschreiben, und dass jedes Objekt aus diesem Array eine url Eigenschaft hat.

Hier ist der Code, der eine Lösung für dieses Problem bietet:

 import React, {Component} from "react" class MemeGenerator extends Component {   constructor() {       super()       this.state = {           topText: "",           bottomText: "",           randomImg: "http://i.imgflip.com/1bij.jpg",           allMemeImgs: []       }       this.handleChange = this.handleChange.bind(this)       this.handleSubmit = this.handleSubmit.bind(this)   }     componentDidMount() {       fetch("https://api.imgflip.com/get_memes")           .then(response => response.json())           .then(response => {               const {memes} = response.data               this.setState({ allMemeImgs: memes })           })   }     handleChange(event) {       const {name, value} = event.target       this.setState({ [name]: value })   }     handleSubmit(event) {       event.preventDefault()       const randNum = Math.floor(Math.random() * this.state.allMemeImgs.length)       const randMemeImg = this.state.allMemeImgs[randNum].url       this.setState({ randomImg: randMemeImg })   }     render() {       return (           <div>               <form className="meme-form" onSubmit={this.handleSubmit}>                   <input                       type="text"                       name="topText"                       placeholder="Top Text"                       value={this.state.topText}                       onChange={this.handleChange}                   />                   <input                       type="text"                       name="bottomText"                       placeholder="Bottom Text"                       value={this.state.bottomText}                       onChange={this.handleChange}                   />                                 <button>Gen</button>               </form>               <div className="meme">                   <img align="center" src={this.state.randomImg} alt="" />                   <h2 className="top">{this.state.topText}</h2>                   <h2 className="bottom">{this.state.bottomText}</h2>               </div>           </div>       )   } } export default MemeGenerator 

Der Schaltfläche Gen kann ein Ereignishandler zugewiesen werden, der beim Klicken darauf auftritt, wie dies bei allen anderen Schaltflächen der Fall ist. Angesichts der Tatsache, dass diese Schaltfläche zum onSubmit des Formulars verwendet wird, ist es jedoch besser, den onSubmit Ereignishandler onSubmit Formulars zu verwenden. In diesem Handler handleSubmit() rufen wir die Methode des Ereignisses event.preventDefault() auf, um das Standardverfahren zum event.preventDefault() von event.preventDefault() abzubrechen, bei dem die Seite neu geladen wird. Als nächstes erhalten wir eine Zufallszahl im Bereich von 0 bis zu dem Wert, der dem Index des letzten Elements des allMemeImgs Arrays entspricht, und verwenden diese Zahl, um auf das Element mit dem entsprechenden Index zu verweisen. Wenn wir uns dem Element randomImg , das das Objekt ist, erhalten wir die Eigenschaft dieser Objekt- url und schreiben sie in die randomImg . Danach wird die Komponente neu gerendert und das Erscheinungsbild der Seite geändert.


Anwendungsseite im Browser

Kursprojekt abgeschlossen.

Zusammenfassung


In dieser Lektion haben Sie eine Anwendung erstellt, die das verwendet, was Sie beim Beherrschen von React gelernt haben. Das nächste Mal werden wir über die Entwicklung moderner React-Anwendungen sprechen und Projektideen diskutieren, deren Implementierung Sie in der Arbeit mit React üben können.

Liebe Leser! Haben Sie beim Abschluss dieses Kursprojekts Schwierigkeiten gehabt?

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


All Articles