Memele sunt grozave – sunt un mod atât de distractiv de a descrie idei și opinii. Deci, nu întâmplător am ales o aplicație generatoare de meme ca proiect capstone în mine curs React gratuit pe Scrimba. Aplicația funcționează prin extragerea unei imagini de meme aleatorii dintr-un API și plasarea textului deasupra acestuia pentru a crea propriul meme personalizat.

Deci, în acest articol, vă voi oferi un ghid pas cu pas pentru crearea aplicației. Dacă vă confundați vreodată, puteți urma acești pași în cursul Scrimba, începând cu această prelegere.

Și apoi, dacă vă place stilul meu de predare și sunteți în starea de spirit pentru o provocare mai dură după ce finalizați acest tutorial, vă rugăm să verificați viitorul meu curs avansat pe Scrimba.

Notă: ar trebui să fiți deja familiarizați cu unele dintre conceptele fundamentale ale React, cum ar fi componentele, starea, elementele de recuzită și metodele ciclului de viață. De asemenea, acest tutorial nu folosește Hooks, dar în cursul meu viitor vom acoperi Hooks în profunzime și vom primi o mulțime de practici folosindu-le.

1. Crearea cazanului și redarea unei componente a aplicației

Crearea sarcinii boilerplate

Primul lucru pe care trebuie să-l facem este să creăm codul boilerplate pentru aplicație. Pentru a face acest lucru, importăm React și ReactDOM si foloseste ReactDOM pentru a reda o componentă numită App, pe care o vom crea mai târziu. Apoi punem App componentă la „rădăcină”. De asemenea, importăm App din dosarul său "./App", pe care îl vom crea în scurt timp.

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

Apoi ne creăm App.js fişier. În el, creăm o componentă funcțională numită App care, deocamdată, returnează un simplu <h1>. Apoi îl exportăm. <h1> ne permite să verificăm dacă aplicația se afișează corect pe ecran.

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

Rezultatul rezultat este următorul:
Rendered Hello World

2. Crearea componentelor Header și MemeGenerator

Crearea activității Header și MemeGenerator

În continuare, creăm componentele Header și MemeGenerator. Antetul va afișa doar elemente, în timp ce MemeGenerator va apela la API și va păstra datele în stare.

Să începem prin a crea Header.js fişier. Deoarece antetul este o componentă care este utilizată doar pentru afișare, ar trebui să fie o componentă funcțională. Deocamdată, componenta ar trebui să returneze un simplu <h1>. După ce l-am creat, apoi exportăm Header.

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

Apoi, creăm MemeGenerator.js fişier. Dupa cum MemeGenerator componentă va ține date și va efectua apeluri către un API, trebuie să fie o componentă de clasă. Încă trebuie să importăm React și, din moment ce va fi o componentă de clasă, vom importa Component de asemenea (care este un denumit import).

MemeGenerator are nevoie de un constructor() care apelează super() și, deoarece va păstra starea, îi adăugăm acum o stare goală. La fel ca în componenta Header, redăm un simplu <h1> a începe cu. Apoi exportăm MemeGenerator.

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

Acum, importăm atât Header, cât și MemeGenerator în App.js și creați o instanță a fiecăruia din componenta aplicației noastre. Pentru a afișa corect componentele, le înfășurăm într-un <div>.

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

3. Finalizarea componentei Header.

Pentru a finaliza <Header> componentă, adăugăm o imagine trollface prin inserarea unui <img> etichetați și setați src la adresa URL a imaginii. Apoi adăugăm un <p> etichetați cu numele aplicației noastre și înfășurați-le pe amândouă în HTML5 semantic <header> etichetă.

function Header() {
  return (
    <header>
      <img
        src="https://www.pngall.com/wp-content/uploads/2016/05/Trollface.png"
        alt="Problem?"
      />
      <p>Meme Generator</p>
    </header>
  );
}

Deoarece stilul este în afara scopului acestui curs, stilurile CSS au fost deja create și aplicate la <header> etichetă. Rezultatul este următorul:

Antet redat

Acestea fiind spuse, cursanții se pot juca întotdeauna cu stilul și își pot perfecționa abilitățile CSS singuri. Cu <Header/> acum complet, restul provocării va avea loc în <MemeGenerator/>

4. Starea de inițializare

Initializarea sarcinii de stat

Acum trebuie să inițializăm starea astfel încât să salveze un text de sus, un text de jos și o imagine aleatorie, care este deja furnizată.

Pentru a face acest lucru, construim obiectul gol pe care l-am așezat în <MemeGenerator/> când am construit-o inițial. Inițializăm topText și bottomText ca șiruri goale și randomImg ca adresă URL furnizată.

class MemeGenerator extends Component {
  constructor() {
    super();
    this.state = {
      topText: '',
      bottomText: '',
      randomImg: 'http://i.imgflip.com/1bij.jpg'
    };
  }
}

5. Efectuarea apelului API

Efectuarea activității de apel API

Apoi, facem un apel API către adresa URL furnizată și salvăm datele returnate (care este o matrice găsită în response.data.memes) la o nouă proprietate de stat numită allMemeImgs.
Când trebuie să încărcăm date dintr-un punct final pentru a le utiliza în componenta noastră, un loc bun pentru a face cererea este componentDidMount() metoda ciclului de viață. De îndată ce componenta se montează, vom folosi nativul fetch() funcție pentru a apela la adresa URL furnizată.

componentDidMount() {
  fetch("https://api.imgflip.com/get_memes")
}

Aceasta returnează o promisiune pe care o transformăm într-un obiect Javascript cu .json() metodă.

componentDidMount() {
  fetch("https://api.imgflip.com/get_memes")
    .then(response => response.json())
}

Apoi primim răspunsul care ne este util trăgând matricea de meme de la response.data.

componentDidMount() {
fetch("https://api.imgflip.com/get_memes")
  .then(response => response.json())
  .then(response => {
  const { memes } = response.data
  })
}

Acum, salvăm rezultatele într-o nouă proprietate de stat numită allMemeImgs. Pentru a face acest lucru, inițializăm allMemeImgs ca o matrice goală.

this.state = {
  topText: '',
  bottomText: '',
  randomImg: 'http://i.imgflip.com/1bij.jpg',
  allMemeImgs: []
};

Acum, înapoi componentDidMount(), stabilim starea. Deoarece nu ne interesează care a fost starea anterioară, ne-am stabilit allMemeImgs la meme.

componentDidMount() {
  fetch("https://api.imgflip.com/get_memes")
    .then(response => response.json())
    .then(response => {
  const { memes } = response.data
  this.setState({ allMemeImgs: memes })
  })
}

Pentru a ne asigura că funcționează, noi console.log primul articol, care arată cam așa:

ieșire console.log

Iată o prezentare generală a întregului componentDidMount() funcţie.

componentDidMount() { //ensure that data is fetched at the beginning
  fetch("https://api.imgflip.com/get_memes") //call to URL
    .then(response => response.json()) //turn promise into JS object
    .then(response => {
  const { memes } = response.data //pull memes array from response.data
  console.log(memes[0]) // check data is present
  this.setState({ allMemeImgs: memes }) // set allMemeImgs state
})
}

6. Crearea formularului de introducere

Acum vrem să creăm un formular care să permită în cele din urmă utilizatorului să introducă textele de sus și de jos. Facem acest lucru cu un HTML <form> etichetă și un simplu <button> care spune „Gen”. Îl modelăm cu CSS-ul furnizat în prealabil.

render() {
  return (
    <div>
      <form className="meme-form">
        <button>Gen</button>
      </form>
    </div>
  )
}

Butonul Gen redat

7. Adăugarea câmpurilor de intrare la formular

Sarcina de adăugare a câmpurilor de intrare

Apoi, depinde de noi să adăugăm cele două câmpuri de introducere (unul pentru textul de sus și unul pentru textul de jos). Formularul ar trebui să fie un formular controlat, așa că va trebui să adăugăm toate atributele necesare pentru ca acesta să funcționeze. Vom crea onChange handler mai târziu.

Creăm două câmpuri de intrare, ambele având tipul text și atribute de nume adecvate (topText și bottomText). În loc să folosim etichete, folosim substituenți: „Text de sus” și „Text de jos”.

În cele din urmă, pentru a face acest lucru un formă controlată, setăm valoarea egală cu valoarea curentă în state cu {this.state.topText} și {this.state.bottomText}.

render() {
  return (
    <div>
      <form className="meme-form">
        <input
          type="text"
          name="topText"
          placeholder="Top Text"
          value={this.state.topText}
        />
        <input
          type="text"
          name="bottomText"
          placeholder="Bottom Text"
          value={this.state.bottomText}
        />
        <button>Gen</button>
      </form>
    </div>
  )
}

8. Crearea handler-ului onChange.

Crearea sarcinii de gestionare onChange

Acum, creăm gestionarul onChange, care va actualiza starea corespunzătoare la fiecare modificare a câmpului de intrare.

În primul rând, creăm un handleChange() funcție care primește un eveniment.

handleChange(event) {

}

Acum, am setat onChange a ambelor câmpuri de intrare să fie egale handleChange.

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

Trebuie să ne amintim să legăm metoda în constructor – un lucru obișnuit pentru dezvoltatorii React.

constructor() {
  super()
  this.state = {
    topText: "",
    bottomText: "",
    randomImg: "http://i.imgflip.com/1bij.jpg",
    allMemeImgs: []
  }
  this.handleChange = this.handleChange.bind(this)
}

Pentru a testa noul handleChange() funcție, adăugăm un simplu console.log:

handleChange(event) {
  console.log("Working!")
}

Dacă se declanșează corect, veți vedea așa ceva:
Rendered console.log („Funcționează!”)

Acum, pentru a completa handleChange() funcţie. Pentru a face acest lucru, vrem să extragem numele și proprietățile valorii din event.target, astfel încât să putem obține numele stării pe care ar trebui să o actualizăm (topText sau bottomText) și valoarea care este introdusă în casetă.

handleChange(event) {
  const { name, value } = event.target
}

Acum le vom folosi pentru a actualiza starea. Deoarece nu suntem interesați de starea anterioară, putem oferi doar un obiect în care am setat [name] la valoarea introdusă în câmpul de intrare.

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

9. Afișarea unei imagini meme alături de textul de sus și de jos

Vrem acum ca aplicația să afișeze o imagine meme alături de textul de sus și de jos. Introducem un <img> eticheta sub <form> și setați randomImg pe care am inițializat-o ca sursă folosind src={this.state.randomImg}. Apoi adăugăm două <h2> etichete care afișează textul corespunzător care este, de asemenea, salvat în stare. Toate acestea sunt înfășurate într-un div și stilat cu pre-furnizate meme clasă.

<div className="meme">
  <img src={this.state.randomImg} alt="" />
  <h2 className="top">{this.state.topText}</h2>
  <h2 className="bottom">{this.state.bottomText}</h2>
</div>

Acum putem testa aplicația tastând în casetele de text. Deoarece starea este setată corect la fiecare apăsare de tastă, textul afișat pe imagine se modifică de fiecare dată când tastăm.

Exemplu de progres dat până acum

10. Afișarea unei imagini meme aleatorii alături de textul de sus și de jos

Afișarea unei sarcini de imagine memo aleatorie

Acum, trebuie să creăm o metodă care afișează o imagine meme pe care o alege aleatoriu din a noastră allMemeImgs matrice atunci când Gen se face clic pe butonul. Proprietatea de pe imaginea aleasă din matrice este .url.
Putem descompune această sarcină în părți mai mici.

În primul rând, setăm formularul onSubmit pentru a egala numele noii noastre metode, pe care o vom numi handleSubmit().

<form className="meme-form" onSubmit={this.handleSubmit}>

Acum creăm handleSubmit() funcție deasupra render() funcţie. Trebuie să prevenim implicit evenimentul, altfel, metoda va încerca să reîmprospăteze pagina.

handleSubmit(event) {
  event.preventDefault()
}

De asemenea, trebuie să ne legăm handleSubmit() în a noastră constructor().

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

Acum, trebuie să obținem un număr aleatoriu, să obținem meme din acel index și să setăm randomImg la .url a articolului aleatoriu.

handleSubmit(event) {
  event.preventDefault()
  // get a random int (index in the array)
  // get the meme from that index
  // set `randomImg` to the `.url` of the random item I grabbed
}

Pentru a obține un număr aleatoriu, folosim Math.floor(Math.random). Pentru a ne asigura că este unul dintre indicii noștri allMemeImgs matrice, înmulțim cu lungimea matricei.

const randNum = Math.floor(Math.random() * this.state.allMemeImgs.length);

Acum am stabilit randMemeImg la egal allMemeImgs, cu indicele de allMemeImgs dupa cum randNum tocmai am primit. Apoi adăugăm .url până la capătul ei.

const randMemeImg = this.state.allMemeImgs[randNum].url;

Acum, tot ce trebuie să facem este să actualizăm starea prin actualizarea proprietății randomImg cu randMemeImg.

this.setState({ randomImg: randMemeImg });

Al nostru finalizat handleSubmit() funcția arată astfel:

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

Generator de meme finalizat

Aplicație de lucru

Acum am finalizat aplicația generator de meme și obținem o imagine diferită de fiecare dată când accesăm Gen , care este apoi suprapus cu textul pe care l-am introdus.

Pentru a continua învățarea, am putea să ne jucăm cu codul și să vedem dacă îl putem îmbunătăți sau putem încerca să obținem imagini dintr-un alt API. Pentru unele practici foarte grele, am putea chiar șterge tot codul și am putea încerca să îl construim din nou de la zero.

Felicitări pentru că ai urmat tutorialul și ai învățat toate abilitățile folosite în acest proiect.

Și dacă sunteți gata pentru asta, verificați viitoarea mea curs avansat, deoarece vă va duce la un nivel profesional în React!