Tutorial React: Cum să începeți și cum se compară

Publicat: 2022-03-11

Front-end și JavaScript în special sunt o lume ciudată. Cantitatea de lucruri noi lansate zilnic este adesea ridiculizată de oamenii care nu lucrează cu ele și de mulți care fac. Totuși, uneori, suntem puțin copleșiți de informații noi, biblioteci și discuții și ne-am dori ceva stabil, cum ar fi un refugiu sigur pentru nave unde să putem sta puțin mai mult. În ultimul timp, React pare să fie acest port docil într-o mare de evoluție dinamică a JavaScript.

Având în vedere acest lucru, am decis să producem acest tutorial React în mai multe părți, pentru a-și prezenta capacitățile și a vedea cum se compară cu Angular și VueJS.

Ilustrație a lui React ca un far afișat clar peste o mare de cod JavaScript

Desigur, React nu este singurul port pe care îl putem folosi, dar în acest moment este una dintre cele mai populare, stabile și inovatoare soluții și, deși încă primește o mulțime de upgrade-uri, acestea sunt mai mult o opțiune de îmbunătățire decât decât o necesitate pentru funcționare.

Starea de reacție în 2019

React este o bibliotecă de vizualizare pe care o putem urmări încă din 2011, când primul său prototip, numit FaxJs, a apărut pe pagina sa de Facebook, React însuși a fost prezentat de Jordan Walke (care este și autorul prototipului menționat) la JSConfUS pe 29 mai 2013 și a fost disponibil în mod deschis pe GitHub pe 2 iulie 2013.

React a continuat să câștige popularitate în 2014, când au început să apară conferințe pentru a extinde comunitatea și a populariza React. Din perspectiva mea, totuși, 2015 a fost un an de hotar pentru React – companiile mari (de exemplu, Airbnb și Netflix) au început să le placă și să adopte soluțiile React. De asemenea, React Native a apărut în acel an. Ideea din spatele React Native nu era ceva absolut nou, dar era interesant de urmărit, mai ales că era susținută de Facebook.

O altă mare schimbare a fost Redux, o implementare Flux. Acest lucru a făcut managementul de stat mult mai accesibil și mai ușor, făcând din aceasta implementarea cea mai de succes de până acum.

Între atunci și acum, o mulțime de alte lucruri au devenit disponibile, inclusiv instrumente React, o rescriere a algoritmului de bază, Fiber, o modificare a versiunilor semantice și așa mai departe. Avanză rapid până astăzi, suntem pe 16.6.3, probabil cu câteva săptămâni înainte ca noua versiune cu Hooks să devină disponibilă (trebuia să fie 16.7.0, dar aceasta este deja lansată din cauza unor remedieri pentru React.lazy). React este bine cunoscut și stabil și primește opinii grozave.

Dar ce este React?

Ei bine, dacă sunteți un dezvoltator front-end și nu ați auzit încă despre asta, atunci trebuie să vă spun că felicitările sunt în regulă, deoarece aceasta este o ispravă.

Glume deoparte, React este o bibliotecă de vizualizare declarativă bazată pe componente care vă ajută să construiți interfața de utilizare. Este o bibliotecă, nu un cadru, deși la început, mulți oameni au descris-o ca fiind cea din urmă.

Evident, dacă vom adăuga Redux, React Router și așa mai departe, începe să aibă toate lucrurile necesare pentru a face o aplicație obișnuită cu o singură pagină, ceea ce ar putea fi un motiv pentru care uneori este caracterizată greșit ca un cadru, mai degrabă decât o bibliotecă. . În orice caz, s-ar putea argumenta că, cu toate componentele acelui mediu împreună, termenul „cadru” se potrivește oarecum, dar în sine, React este doar o bibliotecă.

Să ne oprim cu nomenclatura și să ne concentrăm pe ceea ce este diferit în React, pe lucrurile pe care nu le aveam înainte de apariția lui. În primul rând, când te gândești la React, te gândești la JSX, deoarece este primul lucru care îți vine în vedere când te uiți la cod. JSX este o extensie de sintaxă JavaScript care seamănă oarecum cu HTML/XML. Când vine vorba de React și JSX, avem câteva diferențe față de HTML, de exemplu, o clasă în React este className , nu există tabindex ci tabIndex , stilul acceptă obiecte JavaScript care au proprietăți camelCased și așa mai departe.

Există câteva diferențe minore, dar oricine ar trebui să le ridice în cel mai scurt timp. Gestionarea evenimentelor se face prin, de exemplu, onChange și onClick care pot fi folosite pentru a atașa o funcție pentru a gestiona evenimente. De asemenea, componentele mai târziu pot fi reutilizate și personalizate în mod liber folosind elemente de recuzită, așa că nu există niciun motiv să scrieți același cod de câteva ori.

 import React, { Component } from 'react'; export default class App extends Component { render() { return ( <div>Hello World, {this.props.name}</div> ); } }

Cu toate acestea, JSX nu este de fapt absolut necesar în React. Puteți scrie funcții obișnuite pentru a crea elemente fără a utiliza JSX. Același cod care este mai sus, poate fi folosit ca mai jos.

 import React, { Component } from 'react'; export default class App extends Component { render() { return React.createElement( 'div', null, 'Hello World, ', this.props.name ); } }

Evident, nu vă sugerez să utilizați o astfel de sintaxă, deși există cazuri în care ar putea fi utilă (de exemplu, doriți să introduceți un lucru foarte mic și nu doriți să schimbați mediul de construcție).

De fapt, mai am un motiv pentru care am arătat fragmentul de mai sus. Adesea, dezvoltatorii nu înțeleg de ce trebuie să facem următoarele:

 import React from 'react';

Fragmentul ar trebui să se explice de la sine. Chiar dacă extragem Component , încă avem nevoie de React, deoarece Babel transpilează deasupra JSX la sub React.createElement . Deci, dacă nu importăm React, pur și simplu va eșua pentru noi. Am menționat Babel, care este un instrument care ne ajută să introducem lucruri care nu sunt încă în JavaScript (sau mai degrabă în browsere) sau sunt cumva extensii ale acestuia (sau diferite limbaje precum TypeScript, pe care Babel le suportă din Babel 7). Mulțumesc lui Babel:

  • JSX va fi transformat în funcții care sunt înțelese de browser.
  • Putem folosi funcții noi care nu sunt încă în browsere (de exemplu, proprietățile clasei).
  • Putem adăuga funcții care sunt în browserele mai noi, dar care nu sunt acolo în cele mai vechi, menținând în același timp suportul pentru browser mai vechi.

Pe scurt, mâine este astăzi în JavaScript; acesta este probabil ceva care ar necesita propriul articol. Merită menționat că importul React poate fi ocolit și prin alte tehnici (cum ar fi introducerea ProvidePlugin prin Webpack și așa mai departe), dar din cauza spațiului limitat aici, îl vom evita și vom presupune că utilizatorul va folosi aplicația Create React ( CRA) (mai multe despre acest instrument vor fi menționate mai târziu).

Al doilea lucru important, și mult mai important decât JSX în sine, este că React se bazează pe DOM-ul virtual. Pe scurt, DOM-ul virtual este memoria unui arbore ideal care este reprezentat de JavaScript pe care îl scrie dezvoltatorul, care este comparat ulterior cu DOM real și sincronizat cu acesta într-un proces numit reconciliere.

Cum reacționează în comparație cu Angular și Vue?

Îmi displace destul de mult să compar bibliotecile, mai ales când suntem forțați să comparăm perele cu mere (biblioteci vs. cadre și așa mai departe).

Prin urmare, voi încerca să compar React cu Angular și Vue folosind o serie de întrebări și răspunsuri scurte care nu au mare legătură cu chestii tehnice, mai degrabă decât să spun ceva de genul „X este mai bun decât Y pentru că folosește JSX și nu șabloane. ” Puncte ca acestea sunt de obicei preferințe personale, alegeri subiective ale cuiva. De asemenea, viteza, alocarea memoriei etc., sunt destul de asemănătoare în React și toți concurenții săi majori (imi vine în minte Angular și Vue). Există un raport foarte bun pe această temă, dar vă rugăm să țineți cont de acest lucru: marea majoritate a aplicațiilor nu arată ca niște tabele cu adevărat mari care schimbă rândurile într-un tabel de 10k. Prin urmare, aceste rezultate sunt, de asemenea, un experiment pur de viteză. În lumea reală, nu ai face așa ceva în primul rând.

Ilustrație React vs. Angular vs Vue.js

Deci, să aruncăm o privire la câteva întrebări referitoare la React și la modul în care se compară cu concurența:

Vreau să am o mulțime de oportunități de muncă. Cât de popular este React?

Ei bine, acesta este unul ușor de răspuns - alege React. De fapt, aș spune că React are de aproximativ 6-10 ori (o răspândire destul de mare, dar există unele portaluri unde este 1:50 și altele unde este 1:6) mai multe locuri de muncă deschise decât Vue și de 2-4 ori mai multe decât Angular. Cererea de experți React este puternică, așa că de ce este Vue atât de popular pe GitHub (are mai multe stele decât React, de fapt), dar are mai puține locuri de muncă? Nu am nici o idee.

Îmi doresc o comunitate mare, multe biblioteci, soluții rapide pentru problemele care ar putea apărea.

Reacţiona. Nu mai căuta.

Este ușor de utilizat și face dezvoltarea plăcută?

Încă o dată, conform rapoartelor State of JS pentru 2018 și 2017, atât React, cât și Vue se bucură de o reputație foarte bună și majoritatea dezvoltatorilor spun că le-ar folosi din nou. Angular, pe de altă parte, are tendința, an de an, de a trimite tot mai mulți oameni spunând că nu l-ar mai folosi.

Doresc să creez o nouă aplicație cu o singură pagină, dar nu vreau să caut biblioteci.

Acesta este probabil singurul loc în care aș spune că Angular este alegerea mai bună.

Fără corporații mari. Vreau să fiu cât mai independent posibil, pe care să aleg?

Vue — este singurul independent din marele nostru trio. (Facebook sprijină React, în timp ce Google este în spatele Angular.)

Cel mai ușor început și cea mai rapidă curbă de învățare?

Vede/Reacționează. Mă înclin spre Vue aici, dar aceasta este doar părerea mea personală.

De ce? Pentru că nici măcar nu trebuie să cunoști JSX (este opțional) și practic este doar HTML + CSS + JavaScript.

Tutorial React: Noțiuni introductive pentru prima ta aplicație

Tutorial React: Captură de ecran a mesajului de succes pentru crearea unei aplicații React

Cel mai simplu mod de a începe cu React în zilele noastre este să utilizați CRA, un instrument CLI care creează un proiect pentru dvs. și vă ajută să evitați toate setările necesare pentru Webpack/Babel și multe altele. În schimb, te bazezi pe modul în care este configurat implicit și pe ceea ce a fost inclus în el de-a lungul timpului. Datorită acestui fapt, nu trebuie să vă pese de actualizările majore pentru unele biblioteci critice.

Desigur, mai târziu, vă puteți „ejecta” și gestionați fiecare aspect pe cont propriu, rulând npm run eject . Această abordare are propriile puncte forte, deoarece vă puteți îmbunătăți aplicația cu lucruri care altfel ar fi indisponibile (de exemplu, decoratori), dar poate fi și o sursă de dureri de cap, deoarece necesită multe fișiere suplimentare și mult mai mult timp.

Deci, primul lucru de făcut este:

 npx create-react-app {app-name}

Apoi npm run start și sunteți gata de plecare.

Componente de clasă vs

Ar trebui să începem prin a explica cum diferă aceste componente. Practic, fiecare componentă poate fi o funcție sau o clasă . Principala diferență dintre ele este că clasa 1 are unele caracteristici care sunt indisponibile în componenta funcției: pot avea o stare și pot folosi refs, ciclu de viață etc. Aceasta este starea curentă, iar începând cu versiunea 16.7 (sau oricum va fi fi apelat din cauza modificărilor deja menționate), vom avea și hook-uri, deci state și refs vor fi posibile cu hook-uri.

Există două tipuri de componente de clasă: Component și PureComponent . Singura diferență dintre cele două este că PureComponent face o comparație superficială a recuzitei și a stării — are propriile sale beneficii într-o situație în care nu doriți să faceți randări „irosite”, în care o componentă și copiii săi sunt exact în aceeași stare. după o randare. Totuși, este doar o comparație superficială; dacă doriți să implementați propria comparație (de exemplu, pentru că treceți elemente de recuzită complexe), utilizați doar Component și suprascrieți shouldComponentUpdate (care în mod implicit returnează true). Începând cu 16.6+, ceva similar este disponibil și cu componentele funcției - mulțumită lui React.memo , care este o componentă de ordin superior și se comportă implicit ca PureComponent (comparație superficială), dar este nevoie de un al doilea argument în care puteți trece propria dvs. comparație personalizată de recuzită .

Ca regulă generală, dacă puteți utiliza componenta funcție (nu aveți nevoie de caracteristici de clasă), atunci utilizați-o. În curând, începând cu 16.7.0, utilizarea componentelor de clasă va fi necesară doar din cauza metodelor ciclului de viață. Tind să cred că componentele funcției sunt mai transparente, mai ușor de raționat și de înțeles.

Metode React Lifecycle

Ilustrație pentru montarea, actualizarea și demontarea componentelor

Constructor (recuzită)

  • Opțional, mai ales când CRA este atât de popular, unde declarațiile de câmp de clasă pentru JavaScript sunt incluse implicit. Este inutil să declarați dacă vă legați metodele prin funcție de săgeată în corpul clasei. O stare similară poate fi inițializată și ca proprietate de clasă.
  • Ar trebui să fie folosit numai pentru inițializarea stării locale pentru obiecte și metode de legare în clasele ES6.

componentDidMount()

  • Efectuați apeluri Ajax aici.
  • Dacă aveți nevoie de ascultători de evenimente, abonamente și altele, adăugați-le aici.
  • Puteți utiliza setState aici (dar va face ca componenta să fie redată).

componentWillUnmount()

  • Curăță toate lucrurile care sunt încă în desfășurare - de exemplu, Ajax ar trebui să fie întrerupt, abonamentul dezabonat, cronometrele șterge și așa mai departe.
  • Nu apelați setState , deoarece este inutil deoarece componenta va fi demontată (și veți primi un avertisment).

componentDidUpdate(prevProps, prevState, instantaneu)

  • Se întâmplă când componenta tocmai a terminat actualizarea (nu se întâmplă la randarea inițială).
  • Are trei parametri care sunt opționali de utilizat (recuzită anterioară, stare anterioară și un instantaneu care va apărea numai dacă componenta dvs. implementează getSnapshotBeforeUpdate ).
  • Se întâmplă numai dacă shouldComponentUpdate returnează true.
  • Dacă utilizați setState aici, ar trebui să îl păziți sau veți ateriza într-o buclă infinită.

shouldComponentUpdate(nextProps, nextState)

  • Doar pentru optimizarea performanței.
  • Dacă returnează false, atunci o randare NU va fi invocată.
  • PureComponent poate fi folosit în schimb dacă SCO anulat este doar o comparație de recuzită/stare superficială.

getSnapshotBeforeUpdate()

  • Poate fi folosit pentru a păstra unele informații despre DOM curent, de exemplu, poziția curentă a defilării, care mai târziu poate fi reutilizată în componentDidUpdate pentru a restabili poziția derulării.

componentDidCatch(eroare, informații)

  • Un loc unde ar trebui să apară erori de înregistrare.
  • Se poate apela setState , dar în versiunile viitoare, acesta va fi abandonat în favoarea metodei statice getDerivedStateFromError(error) , care va actualiza starea prin returnarea unei valori pentru a actualiza starea.

Există două metode suplimentare care ambele sunt statice și au fost menționate în alte explicații

static getDerivedStateFromError(eroare)

  • Informațiile despre erori sunt disponibile aici.
  • Ar trebui să returneze o valoare a obiectului care va actualiza starea care poate fi folosită pentru gestionarea erorilor (prin afișarea a ceva).
  • Deoarece este static, nu are acces la instanța componentei în sine.

static getSnapshotBeforeUpdate(recuzite, stare)

  • Ar trebui să fie folosit în cazurile în care elementele de recuzită se schimbă în timp - de exemplu, conform documentelor React, ar putea fi utilă pentru o componentă de tranziție.
  • Deoarece este static, nu are acces la instanța componentei în sine.

Rețineți, mai sunt câteva metode disponibile începând de astăzi, dar ar trebui să fie eliminate în React 17.0, așa că de aceea nu au fost menționate aici.

Stat vs. Recuzită

Să începem cu elementele de recuzită , deoarece sunt mai ușor și mai rapid de explicat. Recuzitele sunt proprietăți care sunt transmise componentei care ulterior pot fi reutilizate în cadrul acesteia pentru afișarea informațiilor/logicii de afaceri și altele asemenea.

 import React, { Component } from 'react'; export default class App extends Component { render() { return ( <div> <HelloWorld name="Someone :)"/> </div> ); } } const HelloWorld = (props) => <div>Hello {props.name}</div>

În exemplul de mai sus, name este o recuzită. Elementele de recuzită sunt doar pentru citire și nu pot fi modificate direct în componentele secundare. De asemenea, există o practică proastă pe care oamenii o fac adesea, și anume copierea recuzitei către stat și operarea statului ulterior. Desigur, există cazuri în care doriți să faceți ceva de genul „starea inițială care va actualiza componenta părinte după trimitere”, dar asta este mai rar – într-un astfel de scenariu, alimentarea stării inițiale ar putea avea sens. De asemenea, nu numai proprietăți precum șiruri de caractere pot fi transmise componentelor copil, ci și numere, obiecte, funcții etc.

Recuzitele au, de asemenea, un lucru util, care se numește defaultProps , un câmp static care vă poate spune care sunt elementele de recuzită implicite pentru o componentă (când acestea nu sunt transmise componentului, de exemplu).

În cazul „stare de ridicare”, în care o componentă (părintele) are o stare care este ulterior reutilizată de copiii săi (de exemplu, un copil o afișează și altul permite editarea), atunci trebuie să transmitem funcția copilului de la părinte, care ne permite să actualizăm statul local al părintelui.

State , pe de altă parte, este o stare locală care poate fi modificată, dar indirect prin utilizarea this.setState . Dacă cineva ar modifica starea direct, componenta nu va fi conștientă de schimbare și nu va fi redată din nou pentru a reflecta modificările menționate la stare.

SetState este o metodă de a schimba obiectul de stare locală (făcând o îmbinare superficială), iar după aceea, componenta răspunde la aceasta prin redarea din nou. Rețineți că, după ce setState este utilizat, proprietatea this.state nu va reflecta imediat modificările menționate în funcție (are o natură asincronă), deoarece câteva instanțe ale setState ar putea fi grupate împreună din cauza optimizării. Are câteva moduri de a fi invocat în cazul în care una dintre aceste posibilități ne permite să facem ceva cu componenta imediat după actualizarea stării:

  • setState({value: '5'})
  • setState((state, props) => ({value: state.name + “'s”}))
  • setState([object / function like above], () => {}) – acest formular ne permite să atașăm callback , care va fi invocat atunci când starea va reflecta datele pe care am vrut să le avem (în primul argument).
 import React, { Component } from 'react'; export default class App extends Component { state = { name: 'Someone :)' } onClick = () => this.setState({ name: 'You' }) render() { return ( <div> <HelloWorld name={this.state.name} onClick={this.onClick}/> </div> ); } } const HelloWorld = (props) => <div onClick={props.onClick}>Hello {props.name}</div>

Contextul de reacție

React a stabilizat recent Context API (care a fost în React de ceva timp, dar a fost o caracteristică experimentală, în ciuda faptului că a fost utilizată pe scară largă de unele dintre cele mai populare biblioteci, cum ar fi Redux), ceea ce ne ajută să rezolvăm o problemă: găurirea elementelor de recuzită. Pe scurt, găurirea elementelor de recuzită este o modalitate de a trece elementele de recuzită profund în structură - de exemplu, poate fi un fel de temă pentru componente, localizare pentru un anumit limbaj, informații despre utilizator și așa mai departe. Înainte de Context (sau mai degrabă înainte de a deveni neexperimental), a fost detaliat prin trecerea într-un mod recursiv de la părinte la copil până la ultima frunză (evident că a existat Redux care ar putea rezolva problema). Fiți conștienți de faptul că această caracteristică rezolvă NUMAI găurirea elementelor de recuzită și nu este un înlocuitor pentru lucruri precum Redux sau Mobx. Evident, dacă utilizați o bibliotecă de management de stat doar pentru asta, atunci o puteți înlocui liber.

Încheierea

Aceasta se încheie prima parte a tutorialului nostru React. În articolele viitoare, sperăm să abordăm subiecte mai avansate, de la stiluri și tipuri de verificare, până la implementarea producției și optimizarea performanței.

Înrudit: Mențineți controlul: un ghid pentru Webpack și React, Pt. 1