Cele mai bune practici cu React Hooks
Publicat: 2022-03-10 React Hooks sunt o nouă adăugare în React 16.8 care vă permit să utilizați stare și alte caracteristici React fără a scrie o componentă class
. Cu alte cuvinte, Hook-urile sunt funcții care vă permit să vă „conectați” la funcțiile React și ale ciclului de viață din componentele funcției. (Nu funcționează în interiorul componentelor class
.)
React oferă câteva Hook-uri încorporate, cum ar fi useState
. De asemenea, vă puteți crea propriile cârlige pentru a reutiliza comportamentul cu stare între diferite componente. Exemplul de mai jos arată un contor a cărui stare este gestionată folosind cârligul useState()
. De fiecare dată când faceți clic pe buton, folosim setCount()
pentru a actualiza valoarea count
cu 1
.
Vedeți Pen [Exemplu React Hook cu Counter](https://codepen.io/smashingmag/pen/QWbXMyM) de Adeneye Abiodun David.
Acest exemplu redă un numărător cu o valoare de 0
. Când faceți clic pe butonul, acesta crește valoarea cu 1
. Valoarea inițială a componentei este definită folosind useState
.
const [count, setCount] = useState(0)
După cum puteți vedea, l-am setat la 0
. Apoi folosim metoda onClick()
pentru a apela setCount
atunci când dorim să creștem valoarea.
<button onClick={() => setCount(count + 1)}> Click me </button>
Înainte de lansarea React Hooks, acest exemplu ar fi folosit mai multe linii de cod, deoarece ar fi trebuit să folosim o componentă de class
.
Regulile React Hooks
Înainte de a ne aprofunda în cele mai bune practici, trebuie să înțelegem regulile React Hooks, care sunt, de asemenea, câteva dintre conceptele fundamentale ale practicilor prezentate în acest articol.
React Hooks sunt funcții JavaScript, dar trebuie să urmați două reguli atunci când le utilizați.
- Call Hooks la nivelul superior;
- Apelați numai Hooks de la componentele React.
Notă : Aceste două reguli au fost introduse în React Hooks, spre deosebire de a face parte din JavaScript în sine.
Să ne uităm la aceste reguli mai detaliat.
Call Hooks la nivel superior
Nu apelați Hooks în bucle, condiții sau funcții imbricate. Utilizați întotdeauna Hooks la nivelul superior al funcției dvs. React. Urmând această regulă, vă asigurați că Hook-urile sunt apelate în aceeași ordine de fiecare dată când o componentă este randată. Acesta este ceea ce permite React să păstreze corect starea Hooks între apelurile multiple useState
și useEffect
.
Să facem o componentă Form
care va avea două stări:
-
accountName
-
accountDetail
Aceste stări vor avea valori implicite, vom folosi cârligul useEffect
pentru a păstra starea fie în stocarea locală a browserului nostru, fie în titlul documentului nostru.
Acum, această componentă va fi poate să își gestioneze cu succes starea dacă rămâne aceeași între apelurile multiple ale useState
și useEffect
.
function Form() { // 1. Use the accountName state variable const [accountName, setAccountName] = useState('David'); // 2. Use an effect for persisting the form useEffect(function persistForm() { localStorage.setItem('formData', accountName); }); // 3. Use the accountDetail state variable const [accountDetail, setAccountDetail] = useState('Active'); // 4. Use an effect for updating the title useEffect(function updateStatus() { document.title = accountName + ' ' + accountDetail; }); // ... }
Dacă ordinea Hook-urilor noastre se schimbă (ceea ce poate fi posibil atunci când sunt apelate în bucle sau condiționale), React va avea dificultăți în a-și da seama cum să păstreze starea componentei noastre.
// ------------ useState('David') // 1. Initialize the accountName state variable with 'David' useEffect(persistForm) // 2. Add an effect for persisting the form useState('Active') // 3. Initialize the accountdetail state variable with 'Active' useEffect(updateStatus) // 4. Add an effect for updating the status // ------------- // Second render // ------------- useState('David') // 1. Read the accountName state variable (argument is ignored) useEffect(persistForm) // 2. Replace the effect for persisting the form useState('Active') // 3. Read the accountDetail state variable (argument is ignored) useEffect(updateStatus) // 4. Replace the effect for updating the status // ...
Acesta este ordinea pe care o urmează React pentru a ne suna cârlige. Deoarece comanda rămâne aceeași, va putea păstra starea componentei noastre. Dar ce se întâmplă dacă punem un apel Hook într-o condiție?
// We're breaking the first rule by using a Hook in a condition if (accountName !== '') { useEffect(function persistForm() { localStorage.setItem('formData', accountName); }); }
Condiția accountName !== ''
este true
la prima randare, așa că rulăm acest Hook. Cu toate acestea, la următoarea randare, utilizatorul poate șterge formularul, făcând condiția false
. Acum că sărim peste acest Hook în timpul redării, ordinea apelurilor Hook devine diferită:
useState('David') // 1. Read the accountName state variable (argument is ignored) // useEffect(persistForm) // This Hook was skipped! useState('Active') // 2 (but was 3). Fail to read the accountDetails state variable useEffect(updateStatus) // 3 (but was 4). Fail to replace the effect
React nu ar ști ce să returneze pentru al doilea apel useState
Hook. React se aștepta ca al doilea apel Hook din această componentă să corespundă efectului persistForm
, la fel ca în timpul randării anterioare - dar nu mai este. Din acel moment, fiecare apel Hook
următor după cel pe care l-am sărit s-a schimbat, de asemenea, cu unul, ceea ce duce la erori.
Acesta este motivul pentru care Hooks trebuie să fie numit la nivelul superior al componentelor noastre. Dacă vrem să rulăm un efect condiționat, putem pune acea condiție în Hook-ul nostru.
Notă : Consultați documentele React Hook pentru a citi mai multe despre acest subiect.
Numai cârlige de apel de la React Components
Nu apelați Hooks din funcțiile JavaScript obișnuite. În schimb, puteți apela Hooks din componentele funcției React. Să ne uităm la diferența dintre funcția JavaScript și componenta React de mai jos:
Funcția JavaScript
import { useState } = "react"; function toCelsius(fahrenheit) { const [name, setName] = useState("David"); return (5/9) * (fahrenheit-32); } document.getElementById("demo").innerHTML = toCelsius;
Aici importăm cârligul useState
din pachetul React și apoi ne declarăm funcția. Dar acest lucru este invalid, deoarece nu este o componentă React.
Funcția de reacție
import React, { useState} from "react"; import ReactDOM from "react-dom"; function Account(props) { const [name, setName] = useState("David"); return <p>Hello, {name}! The price is <b>{props.total}</b> and the total amount is <b>{props.amount}</b></p> } ReactDom.render( <Account total={20} amount={5000} />, document.getElementById('root') );
Chiar dacă corpul ambelor arată similar, acesta din urmă devine o componentă atunci când importăm React în fișier. Acesta este ceea ce ne face posibil să folosim lucruri precum JSX și cârlige React în interior.
Dacă s-a întâmplat să importați cârligul preferat fără să importați React (ceea ce îl face o funcție obișnuită), nu veți putea să utilizați cârligul pe care l-ați importat, deoarece acesta este accesibil doar în componenta React.
Call Hooks de la Custom Hooks
Un Hook personalizat este o funcție JavaScript al cărei nume începe cu use
și care poate apela alte Hook. De exemplu, useUserName
este folosit sub un Hook personalizat care apelează hook- useState
și useEffect
. Acesta preia date dintr-un API, parcurge datele și apelează setIsPresent()
dacă numele de utilizator specific pe care l-a primit este prezent în datele API.

export default function useUserName(userName) { const [isPresent, setIsPresent] = useState(false); useEffect(() => { const data = MockedApi.fetchData(); data.then((res) => { res.forEach((e) => { if (e.name === userName) { setIsPresent(true); } }); }); }); return isPresent; }
Apoi putem continua să reutilizam funcționalitatea acestui cârlig în alte locuri unde avem nevoie de astfel de funcții în aplicația noastră. În astfel de locuri, cu excepția cazului în care este necesar, nu mai trebuie să apelăm la useState
sau useEffect
.
Urmând această regulă, vă asigurați că toată logica cu stare într-o componentă este clar vizibilă din codul sursă.
Pluginul ESLint
Pluginul ESLint numit eslint-plugin-react-hooks
impune regulile de mai sus. Acest lucru este util în aplicarea regulilor atunci când lucrați la un proiect. Vă sugerez să utilizați acest plugin atunci când lucrați la proiectul dvs., mai ales când lucrați cu alții. Puteți adăuga acest plugin la proiectul dvs. dacă doriți să îl încercați:
// Your ESLint configuration { "plugins": [ // ... "react-hooks" ], "rules": { // ... "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies } }
Acest plugin este inclus implicit în aplicația Create React. Deci nu trebuie să-l adăugați dacă porniți aplicațiile React folosind Create-React-App.
Gândind în cârlige
Să aruncăm o scurtă privire asupra componentelor class
și a componentelor funcționale (cu Hooks), înainte de a ne arunca în cele câteva bune practici Hooks.
Cel mai simplu mod de a defini o componentă în React este să scrieți o funcție JavaScript care returnează un element React:
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
Componenta Welcome
acceptă elemente de props
care este un obiect care conține date și returnează un element React. Putem apoi importa și reda această componentă într-o altă componentă.
Componenta class
folosește o metodologie de programare numită Encapsulation , ceea ce înseamnă practic că tot ceea ce este relevant pentru componenta de clasă va locui în ea. Metodele ciclului de viață ( constructors
, componentDidMount()
, render
și așa mai departe) conferă componentelor o structură previzibilă.
Încapsularea este unul dintre elementele fundamentale ale OOP ( Programare orientată pe obiecte). Se referă la gruparea de date în cadrul metodelor care operează pe acele date și este folosit pentru a ascunde valorile sau starea unui obiect de date structurate în interiorul unei clase - împiedicând accesul direct al părților neautorizate la acestea.
Cu Hooks, compoziția unei componente se schimbă de la a fi o combinație de Hook-uri pe ciclul de viață - la funcționalități cu unele randări la sfârșit.
Componenta funcției
Exemplul de mai jos arată cum pot fi folosite cârlige personalizate într-o componentă funcțională (fără a arăta ce este corpul). Cu toate acestea, ceea ce face sau poate face nu este limitat. Ar putea fi instanțierea variabilelor de stare, consumarea contextelor, abonamentul componentei la diferite efecte secundare - sau toate cele de mai sus dacă utilizați un cârlig personalizat!
function { useHook{...}; useHook{...}; useHook{...}; return (
...); }
Componenta clasei
O componentă class
vă cere să vă extindeți din React.Component
și să creați o funcție de render
care returnează un element React. Acest lucru necesită mai mult cod, dar vă va oferi și câteva beneficii.
class { constructor(props) {...} componentDidMount() {...} componentWillUnmount() {...} render() {...} }
Există câteva beneficii pe care le obțineți prin utilizarea componentelor funcționale în React:
- Va deveni mai ușor să separați componentele container și prezentare, deoarece trebuie să vă gândiți mai mult la starea componentei dvs. dacă nu aveți acces la
setState()
în componenta dvs. - Componentele funcționale sunt mult mai ușor de citit și testat , deoarece sunt funcții JavaScript simple, fără stări sau cicluri de viață.
- Ajungi cu mai puțin cod.
- Echipa React a menționat că poate exista o creștere a performanței componentelor funcționale în versiunile viitoare React.
Acest lucru duce la prima cea mai bună practică atunci când utilizați React Hooks.
Cele mai bune practici Hooks
1. Simplificați-vă cârligele
Menținerea simplă a React Hooks vă va oferi puterea de a controla și manipula eficient ceea ce se întâmplă într-o componentă de-a lungul vieții sale. Evitați pe cât posibil să scrieți cârlige personalizate ; puteți introduce un useState()
sau useEffect()
în loc să vă creați propriul cârlig.
Dacă vă descoperiți că utilizați o mulțime de cârlige personalizate care sunt legate de funcționalitate, puteți crea un cârlig personalizat care acționează ca un înveliș pentru acestea. Să aruncăm o privire la două componente funcționale diferite cu cârlige de mai jos.
Componentă funcțională v1
function { useHook(...); useHook(...); useHook(...); return( <div>...</div> ); }
Componenta funcțională v2
function { useCustomHook(...); useHook(...); useHook(...); return( <div>...</div> ); }
v2 este o versiune mai bună, deoarece menține cârligul simplu și toate celelalte useHook
uri sunt în linie în consecință. Acest lucru ne permite să creăm funcționalități care pot fi reutilizate în diferite componente și, de asemenea, ne oferă mai multă putere de a controla și manipula componentele în mod eficient. În loc să adoptați v1 în care componentele noastre sunt pline de cârlige, ar trebui să utilizați v2, care va face depanarea ușoară și codul mai curățat.
2. Organizați și structurați-vă cârligele
Unul dintre avantajele React Hooks este capacitatea de a scrie mai puțin cod ușor de citit. În unele cazuri, cantitatea de useEffect()
și useState()
poate fi încă confuză. Când vă mențineți componenta organizată, va ajuta la lizibilitate și vă va menține fluxul componentelor consistent și previzibil. Dacă Hook-urile dvs. personalizate sunt prea complicate, le puteți oricând descompune în Hook-uri sub-personalizate. Extrageți logica componentei dvs. în Hooks personalizate pentru a vă face codul ușor de citit.
3. Folosiți React Hooks Snippets
React Hooks Snippets este o extensie Visual Studio Code pentru a face React Hooks mai ușor și mai rapid. În prezent, sunt acceptate cinci cârlige:
-
useState()
-
useEffect()
-
useContext()
-
useCallback()
-
useMemo()
Au fost adăugate și alte fragmente. Am încercat să lucrez cu aceste cârlige și a fost una dintre cele mai bune practici pe care le-am folosit personal în timp ce lucram cu ele.
Există două moduri în care puteți adăuga fragmente React Hooks la proiectul dvs.:
- Comanda
Lansați VS Code Quick open ( Ctrl + P ), lipițiext install ALDuncanson.react-hooks-snippets
și apăsați Enter . - Piața de extensii
Lansați „VS Code Extension Marketplace” ( Ctrl + Shift + X ) și căutați „React Hook Snippets”. Apoi, căutați pictograma „Alduncanson”.
Recomand primul fragment. Citiți mai multe despre fragmente aici sau verificați cele mai recente fragmente Hooks aici.
4. Luați în considerare regulile Hooks
Încercați să luați întotdeauna în considerare cele două reguli ale Hooks pe care le-am învățat mai devreme în timp ce lucrați cu React Hooks.
- Sună-ți Hooks doar la nivelul superior. Nu apelați Hook-uri în bucle, condiții sau funcții imbricate.
- Apelați întotdeauna Hook-uri din componentele funcției React sau din Hook-uri personalizate, nu apelați Hook-uri din funcțiile JavaScript obișnuite.
Plugin-ul ESlint numit eslint-plugin-react-hooks
impune aceste două reguli, puteți adăuga acest plugin la proiectul dvs. dacă doriți, așa cum explicăm mai sus în secțiunea regulilor de cârlige.
Cele mai bune practici nu au fost complet rezolvate, deoarece Hook-urile sunt încă relativ noi. Deci, adoptarea ar trebui luată cu precauție pe care s-ar lua în adoptarea oricărei tehnologii timpurii. Având în vedere asta, Hooks reprezintă calea pentru viitorul React.
Concluzie
Sper că v-a plăcut acest tutorial. Am învățat cele mai importante două reguli ale React Hooks și cum să gândim eficient în Hooks. Am analizat componentele funcționale și unele bune practici în scrierea Hooks în mod corect și eficient. Oricât de scurte sunt regulile, este important să le faceți busola dvs. de ghidare atunci când scrieți reguli. Dacă sunteți predispus să-l uitați, puteți utiliza pluginul ESLint pentru a-l aplica.
Sper că veți prelua toate lecțiile învățate aici în următorul proiect React. Noroc!
Resurse
- „Prezentarea cârligelor”, React Docs
- „Funcțional vs Componente de clasă în reacție”, David Joch, Medium
- „Mixinele considerate dăunătoare”, Dan Abramov, React Blog
- „React Hooks: Cele mai bune practici și o schimbare în mentalitate”, Bryan Manuele, mediu
- „React Hooks Snippets For VS Code”, Anthony Davis, Visual Code Marketplace