Kõige populaarsemate React konksude sügavam uurimine
Pawel Rybczynski
Software Engineer
Paljude intervjuude käigus olen märganud, et isegi kogenud programmeerijatel on probleeme konksude eristamisega, rääkimata nende keerukamatest võimalustest. Seega püüan selles artiklis selgitada, kuidas Hooks'e tuleks kasutada.
Kõige olulisemad asjad, mida peate meeles pidama Hooks'i kohta:
neid saab kasutada ainult funktsioonikomponentides - klassikomponentidel on oma elutsükli rakendamine;
nad alustavad alati kasutada;
võite kasutada nii palju konksusid kui soovite, kuid peate meeles pidama, et nende kasutamine mõjutab üldist jõudlust;
neid tuleb täita samas järjekorras igal renderdamisel... aga miks? Vaatame ühte näidet:
<code>srcFunctionComponent.js
Rida 11:5: React Konks "useEffect" kutsutakse tingimuslikult. <strong>React Konksud</strong> peab olema kutsutud täpselt samas järjekorras igas komponendis render .eslintreact-hooks/rules-of-hooks
Nagu näete, on see ainult eslint hoiatus, nii et saate selle keelata, lisades käsu altpoolt ülevalt alla käsu FunctionComponent
/* eslint-disable react-hooks/rules-of-hooks */
ja see töötab, kuid ainult seni, kuni me täidame tingimuse, mis juhib meie konksu. Kõige järgmine asi, mida me näeme, on see viga.
Ebaõnnestunud viga: Renderdatud rohkem konksusid kui eelmise renderduse ajal.
React 5
FunctionComponent FunctionComponent.js:11
React 12
unstable_runWithPriority scheduler.development.js:468
React 17
js index.js:7
js main.chunk.js:905
Webpack 7
react-dom.development.js:15162
Miks see juhtub? React tugineb konksude kutsumise järjekorrale, kuna React ei teaks, mida useEffecti puhul tagastada, sest reas ei olnud sellist konksu, mida kontrollida.
Pidage meeles, et eslint on võimas tööriist, see aitab meil leida palju võimalikke vigu ja vigu. Selle hoiatuste välja lülitamine on ohtlik, kontrollige alati, kas hoiatuse ignoreerimine võib põhjustada rakenduse krahhi.
useState
Ilmselt teate, kuidas see välja näeb 😉.
const [value, setValue] = useState(0);
Seega on teil 4 elementi: olek (reaktiivne väärtus), uuendamisfunktsioon (määraja), tegelik konks (funktsioon) ja valikuline algväärtus. Miks see tagastab massiivi? Sest me saame seda ümber struktureerida nii, nagu meile meeldib.
Nüüd tahan keskenduda viimasele elemendile - algväärtusele. Algseisundi üleandmiseks on kaks võimalust:
Kõvakooditud väärtuse või midagi muud - mida kutsutakse iga renderduse korral üles.
const [value, setValue] = useState(0);
Funktsiooni versiooniga. See on tõesti kasulik, kui me tahame käivitada algseisundit ainult üks kord, kohe esimesel renderdamisel. Võib-olla on vaja teha palju keerulisi arvutusi, et saada algseisundit? See vähendab kenasti ressursikulusid, jee!
Veel üks asi, mis võib tekitada vigu rakenduse töövoogudes: sa ilmselt tead, kuidas olekut uuendada, eks ole?
setValue(1);
Õige... aga mis siis, kui ma tahan uuendada olekut eelmise oleku põhjal?
setValue(value + 1);
Jah... Aga ei... Mis siis, kui sa üritad setter-funktsiooni kaks korda järjest kutsuda? Soovitatav viis oleku uuendamiseks eelmise oleku põhjal on kasutada funktsiooni. See tagab, et te viitate eelmisele olekule
See Hook võtab 2 argumenti (teine on valikuline) ja me kasutame seda kõrvalmõjude käsitlemiseks. Ja sõltuvalt sellest, mida me teise argumendina edasi anname, kutsutakse konks erinevalt:
ilma teise argumendita - iga renderdamine
useEffect(() => {
doSomething();
});
tühi massiivi - ainult esimesel renderdamisel
useEffect(() => {
doSomething();
}, []);
massiivi koos sõltuvustega - iga kord, kui väärtus sõltuvuste massiivi sees muutub
UseEffecti abil saame kasutada midagi, mida nimetatakse puhastamiseks. Milleks see on? See on väga kasulik, kuid ma arvan, et see on kõige parem sündmuste kuulajate puhastamiseks. Oletame, et soovite luua sündmuse kuulaja, mis sõltub mõnest olekust. Sa ei taha lisada uut sündmuse kuulajat iga oleku muutuse korral, sest mõne renderduse järel on kuulajaid nii palju, et see mõjutab rakenduse jõudlust. Suurepärane viis selliste asjade vältimiseks on kasutada cleanup funktsiooni. Kuidas seda teha? Lihtsalt lisage useEffecti juurde tagastusfunktsioon.
Kuna see on useEffect Hook'i sees, kutsutakse tagastus sõltuvalt sõltuvuse massiivi - igal renderdamisel, ainult esimesel renderdamisel või kui väärtus sõltuvuse massiivi muutub. Aga kui komponent eemaldatakse, kutsutakse puhastamine teise argumendi kohta igal juhul. Tagasipöördumine kood kutsutakse enne tegelikku koodi Hookist. See on väga loogiline - kõigepealt puhastatakse vana, seejärel luuakse uus. Õige?
Alguses tundub see ok. Sa hangid mõned andmed ja kui andmed tulevad, uuendad olekut. Ja siin ongi lõks:
Mõnikord saate sellise hoiatuse: Ei saa teha React oleku uuendamist monteerimata komponendile. See ei ole võimalik, kuid see viitab mälulekkele teie rakenduses. Selle parandamiseks tühistage kõik tellimused ja asünkroonsed ülesanded useEffecti puhastusfunktsioonis.
Põhjus on selles, et komponenti saab vahepeal lahti monteerida, kuid rakendus üritab ikkagi selle komponendi olekut pärast lubaduse täitmist uuendada. Kuidas sellega toime tulla? Tuleb kontrollida, kas komponent on olemas.
Märkus: On olemas väga sarnane Hook => useLayoutEffect() - callback käivitub pärast komponendi renderdamist, kuid enne domi visuaalset uuendamist. See on kasulik, kui töötate getBoundingClientRect() funktsiooniga, kuid te peaksite vaikimisi kasutama useEffecti. Miks? Sest see võib blokeerida visuaalsed uuendused - kui teil on keeruline kood oma efekti Hook sees.
useContext
Milleks see on? Andmete jagamine ilma rekvisiitide edastamiseta. Koosneb järgmistest elementidest:
Loodud kontekst - andmed
Konteksti pakkuja - pakkuda konteksti kõigile lastele
Edastatud väärtus - andmed, mida soovite jagada
Hook - jagatud andmete lugemiseks
const user = {
name: "Adam",
lastName: "Kowalski",
};
eksport const UserContext = createContext(user);
;
```
Lapses tuleb importida kontekst ja kutsuda useContext Hook ning anda kontekst argumendina üle.
import { UserContext } from "./App";
const { name } = useContext(UserContext);
return <h1>Tere {nimi}<>
```
Voilà. Näeb lahe välja. Peamiselt globaalsete andmete, nagu teemad jne, edastamiseks. Ei ole soovitatav kasutada väga dünaamiliste muutustega ülesannetes.
Loomulikult võime luua kohandatud kontekstipakkuja ja kohandatud konksu, et vähendada selle asemel boilerplate'i... aga ma tegelen kohandatud konksudega järgmises artiklis.
useReducer
See võimaldab meil hallata olekut ja uuesti esitada, kui olek muutub - nagu useState. See on sarnane redux reduceriga. See on parem kui useState, kui oleku loogika on keerulisem.
Millal seda kasutada? Kui tahame saavutada referentsiaalset võrdsust (vähendades seeläbi loodud funktsioonide arvu). See Hook tagastab funktsiooni, erinevalt useMemo, mis tagastab väärtuse.
Näide: Loo funktsioon vanemkomponendis ja anna see siis üle rekvisiitide kaudu.
Seejärel kontrollige lapskomponendis, mitu korda kutsutakse efekti Hook pärast selle funktsiooni lisamist sõltuvuse massiivi:
// Laps
useEffect(() => {
console.log("getSquaredValue", getSquaredValue());
}, [getSquaredValue]);
See logib konsooli igal renderdamisel! Isegi kui väärtused sees on getSquaredValue() funktsioon ei muutunud. Kuid me saame seda vältida, kui pakime selle funktsiooni useCallbacki sisse.
See ei ole neutraalne, kui vaadata ressursikulusid - useMemo tuleb kutsuda iga renderduse puhul, salvestab väärtuse mällu ja võrdleb (mälu koormus),
kasutab Memoization - optimeerimistehnika, spetsiifiline vorm vahemälu.
Seda tuleks kasutada ainult 2 stsenaariumi puhul:
Kui soovite vältida keerulise koodi kutsumist iga renderduse puhul;
Kui soovite saavutada referentsiaalset võrdsust.
Vaadakem teist juhtumit veidi lähemalt. Me tahame kasutada useEffecti koos objektiga kui sõltuvusega. Kuna objekte võrreldakse nende viite järgi, siis kutsutakse useEffect iga renderduse korral. Sellise asja vältimiseks saame useEffecti kombineerida useMemoga, et memoida sellised objektid ja seejärel anda see memoiseeritud objektid sõltuvuse massiivi. Lühike näide:
Objekt 'hobbit' muudab useEffect Hook'i (rida 49) sõltuvusi igal renderdamisel. Liigutage see useEffecti tagasikutsumise sees. Alternatiivselt mähkige 'hobbit' initsialiseerimine oma useMemo () konksu sisse.eslintreact-hooks/exhaustive-deps
Kõige tähtsam: useRef ei käivita uuesti renderdamist (nagu useState), sest see ei ole seotud renderdamistsükliga - see säilitab sama viite renderdamiste vahel.
const ref = useRef(0);
Salvestatud väärtuse kutsumiseks tuleb kasutada praegust omadust (ref on objekt) - ref.current
Teine juhtum, mille puhul me saame seda konksu kasutada, on viidata elementidele HTML-i sees. Igal elemendil on atribuut ref. Nii saame käsitleda fookust, sündmusi jne.
Kolmas juhtum on see, et me saame kasutada refs'i kontrollimatute komponentide käsitlemiseks. Nende kohta saate rohkem lugeda dokumendis reageeri dokumente, kuid lühidalt öeldes näeb see välja nii:
Nagu näete, puudub sündmuse käsitseja, see lihtsalt jätab meelde sisestatud väärtuse. See sobib suurepäraselt lihtsate vormide käsitlemiseks, kui soovite lihtsalt lugeda salvestatud väärtusi, kui neid vajate (näiteks saatmisel).
Boonus: see on suurepärane, kui teil on vaja meeles pidada eelmisi olekuväärtusi. Võite kasutada selleks useEffect Hook'i, lihtsalt edastage olek ref'ile.
Nagu näete, ei ole konksud nii ilmselged. Me saame neid kombineerida, et lahendada paljusid probleeme. Selle teema uurimisest on teile kindlasti palju kasu.
Ja seal on ka kohandatud konksud...
Kokkuvõttes, React konksud on revolutsiooniliselt muutnud React arendajad lähenemine hoonele veebirakendused . Andes intuitiivsema ja tõhusama viisi funktsionaalsete komponentide oleku ja elutsükli haldamiseks, on konksud muutunud lahutamatuks osaks React arendus .
Olenemata sellest, kas olete kogenud arendaja või alles alustate React-ga, on kõige populaarsemate konksude ja nende kasutusjuhtumite mõistmine väga oluline. Sellised konksud nagu useState, useEffect, useContext ja muud, React komponendid saab ehitada puhtama ja taaskasutatavama koodiga. Lisaks sellele on võimalik luua kohandatud konksud võimaldab arendajatel kapseldada ja jagada loogikat mitme komponendi vahel, edendades koodi taaskasutatavust ja modulaarsust. Kuna React areneb edasi ja võtab kasutusele uusi funktsioone, mängivad konksud kahtlemata keskset rolli raamistiku kogu potentsiaali ärakasutamisel.
Seega, olenemata sellest, kas te töötate väikese funktsioonirakenduse või suure veebirakenduse kallal, on omaksvõtmine React konksud parandab teie arendustöö sujuvust ja avab hulgaliselt võimalusi jõulise ja funktsionaalselt rikkaliku tarkvara loomiseks. React rakendused .