Per daugelį pokalbių pastebėjau, kad net patyrę programuotojai susiduria su sunkumais atskirti kabliukus, jau nekalbant apie pažangesnes jų galimybes. Taigi šiame straipsnyje pabandysiu paaiškinti, kaip reikėtų naudoti kabliukus.
Svarbiausi dalykai, kuriuos reikia prisiminti apie kabliukus:
juos galima naudoti tik funkcijų komponentuose - klasių komponentai turi savo gyvavimo ciklo įgyvendinimą;
jie visada prasideda nuo naudoti;
galite naudoti tiek kabliukų, kiek tik norite, tačiau reikia nepamiršti, kad jų naudojimas turi įtakos bendram našumui;
jie turi būti atliekami ta pačia tvarka kiekviename atvaizdavime... bet kodėl? Pažvelkime į pavyzdį:
<code>srcFunctionComponent.js
11:5 eilutė: React Kablys "useEffect" iškviečiamas sąlyginai. <strong>React Kabliukai</strong> kiekviename komponente turi būti iškviečiamas ta pačia tvarka atvaizduoti .eslintreact-hooks/rules-of-hooks
Kaip matote, tai tik eslint įspėjimas, todėl galite jį išjungti pridėdami komandą iš apačios į viršų Funkcijos komponentas
/* eslint-disable react-hooks/rules-of-hooks */
ir jis veiks, bet tik tol, kol įvykdysime sąlygą, pagal kurią veikia mūsų Kablys. Kitas dalykas, kurį pamatysime, yra ši klaida.
Neištaisyta klaida: Atvaizduota daugiau kabliukų nei per ankstesnį atvaizdavimą.
React 5
Funkcijų komponentas 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
Kodėl taip nutinka? React remiasi kabliukų iškvietimo tvarka, nes React nežinotų, ką grąžinti už useEffect, nes eilutėje nebuvo tokio kabliuko, kurį būtų galima patikrinti.
Atminkite, kad "eslint" yra galingas įrankis, jis padeda mus sugauti daug galimų klaidų ir klaidų. Išjungti įspėjimus yra pavojinga, todėl visada patikrinkite, ar ignoruojant įspėjimą gali sutrikti programos veikimas.
useState
Tikriausiai žinote, kaip tai atrodo 😉
const [value, setValue] = useState(0);
Taigi, turite 4 elementus: būseną (reactive vertė), atnaujinimo funkciją (setter), faktinį kabliuką (funkciją) ir neprivalomą pradinę vertę. Kodėl grąžinamas masyvas? Todėl, kad galime jį pertvarkyti, kaip tik norime.
Dabar noriu sutelkti dėmesį į paskutinį elementą - pradinę vertę. Pradinę būseną galima perduoti dviem būdais:
Pagal kietai užkoduotą reikšmę ar kt., kuri bus iškviečiama kiekvieno atvaizdavimo metu.
const [value, setValue] = useState(0);
Pagal funkcijos versiją. Tai labai naudinga, jei pradinę būseną norime paleisti tik vieną kartą, per patį pirmąjį atvaizdavimą. Galbūt norint gauti pradinę būseną reikia atlikti daug sudėtingų skaičiavimų? Tai gražiai sumažins išteklių sąnaudas, yay!
Dar vienas dalykas, dėl kurio gali atsirasti klaidų programėlės sraute: tikriausiai žinote, kaip atnaujinti būseną, tiesa?
setValue(1);
Teisingai... bet ką daryti, jei noriu atnaujinti būseną pagal ankstesnę būseną?
setValue(value + 1);
Taip... Bet ne... Kas, jei bandysite du kartus iš eilės iškviesti setter funkciją? Rekomenduojamas būdas atnaujinti būseną pagal ankstesnę būseną - naudoti funkciją. Ji garantuoja, kad remiatės į ankstesnę būseną
Šis Kablys priima 2 argumentus (antrasis argumentas neprivalomas) ir naudojamas šalutiniams efektams tvarkyti. Priklausomai nuo to, ką perduosime kaip antrąjį argumentą, kabliukas bus iškviestas skirtingai:
be antrojo argumento - kiekvienas atvaizdavimas
useEffect(() => {
doSomething();
});
tuščias masyvas - tik pirmojo atvaizdavimo metu
useEffect(() => {
doSomething();
}, []);
masyvą su priklausomybėmis - kiekvieną kartą, kai pasikeičia priklausomybių masyvo reikšmė.
Naudodami funkciją useEffect galime naudoti tai, kas vadinama valymu. Kam jis skirtas? Jis labai naudingas, bet manau, kad geriausiai tinka įvykių klausytojams valyti. Tarkime, norite sukurti įvykio klausytoją, kuris priklauso nuo tam tikros būsenos. Nenorite pridėti naujo įvykių klausytojo kiekvienam būsenos pasikeitimui, nes po kelių atvaizdavimų klausytojų bus tiek daug, kad tai turės įtakos programos našumui. Puikus būdas išvengti tokių dalykų - naudoti valymo funkciją. Kaip tai padaryti? Tiesiog pridėkite grąžinimo funkciją prie funkcijos useEffect.
Kadangi tai yra "useEffect Hook" viduje, grąžinimo funkcija iškviečiama priklausomai nuo priklausomybių masyvo - kiekvieno atvaizdavimo metu, tik pirmojo atvaizdavimo metu arba kai pasikeičia priklausomybių masyvo reikšmė. Tačiau kai komponentas išmontuojamas, valymas bus iškviestas antrajam argumentui nepriklausomai nuo to, koks jis bus. Grąžinimas kodas iškviečiamas prieš tikrąjį "Hook" kodą. Tai labai logiška - iš pradžių išvalykite seną, tada sukurkite naują. Tiesa?
Iš pradžių viskas atrodo gerai. Jūs gaunate keletą duomenys, o gavę duomenų atnaujinkite būseną. Ir čia yra spąstai:
Kartais gausite tokį įspėjimą: Negalima atlikti React būsenos atnaujinimo neįmontuotam komponentui. Tai neveikia, tačiau tai rodo, kad jūsų programoje yra atminties nutekėjimas. Norėdami ištaisyti, atšaukite visas prenumeratas ir asinchronines užduotis useEffect valymo funkcijoje.
Taip yra todėl, kad komponentas tuo metu gali būti atjungtas, tačiau programa vis tiek bandys atnaujinti to komponento būseną po to, kai pažadas bus įvykdytas. Kaip tai išspręsti? Reikia patikrinti, ar komponentas egzistuoja.
Pastaba: yra labai panašus Hook => useLayoutEffect() - grįžtamasis skambutis paleidžiamas atvaizdavus komponentą, bet prieš vizualiai atnaujinant domą. Tai naudinga dirbant su getBoundingClientRect(), tačiau pagal nutylėjimą turėtumėte naudoti useEffect. Kodėl? Nes jis gali blokuoti vizualinius atnaujinimus - kai efekto "Hook" viduje turite sudėtingą kodą.
useContext
Kam jis skirtas? Dalijimasis duomenimis neperduodant rekvizitų. Sudaro šie elementai:
Sukurtas kontekstas - duomenys
Konteksto teikėjas - suteikite kontekstą visiems vaikams
Perduota reikšmė - duomenys, kuriais norite dalytis
"Child" programoje reikia importuoti kontekstą ir iškviesti "useContext" kabliuką bei perduoti šį kontekstą kaip argumentą.
importuoti { UserContext } iš "./App";
const { name } = useContext(UserContext);
return <h1>Sveiki {vardas}<>
```
Voilà. Atrodo šauniai. Daugiausia skirtas visuotiniams duomenims, pavyzdžiui, temoms ir pan., perduoti. Nerekomenduojama naudoti užduotyse su labai dinamiškais pokyčiais.
Žinoma, galime sukurti pasirinktinį konteksto teikėją ir pasirinktinį kabliuką, kad sumažintume šablonų skaičių... bet apie pasirinktinius kabliukus kalbėsiu kitame straipsnyje.
useReducer
Ji leidžia valdyti būseną ir iš naujo atvaizduoti, kai būsena pasikeičia - kaip ir useState. Jis panašus į redux reduktorius. Šis būdas yra geresnis nei useState, kai būsenos logika yra sudėtingesnė.
Kam jis skirtas? Ją galima naudoti, kai norime atstatyti būseną į pradinę vertę. Toliau rasite gražų pavyzdį:
// Tėvas
// Vaikas
funkcija init(initialNumber) {
return { number: initialNumber };
}
funkcija reducer(state, action) {
switch (action.type) {
case "change":
return { number: Math.random() };
atvejis "iš naujo":
return init(action.payload);
numatytoji reikšmė:
mesti naują Error();
}
}
export default funkcija ChildComponent({ getFactorial }) {
const [state, dispatch] = useReducer(reducer, initialNumber, init);
return (
<>
<h2>Skaičius: {state.number}</h2>
<button
onclick="{()" > išsiųsti({ tipas: "iš naujo nustatyti", krovinys: initialNumber })}
>
Iš naujo nustatyti
</button>
<button onclick="{()" > išsiųsti({tipas: "pakeisti" })}>Padaryti</button>
</>
);
}
Skaičius: {state.number}
useCallback
Kada jį naudoti? Kai norime pasiekti referencinę lygybę (taip sumažindami sukurtų funkcijų skaičių). Šis kabliukas grąžina funkciją, kitaip nei useMemo, kuris grąžina reikšmę.
Pavyzdys: Sukurkite funkciją pagrindiniame komponente ir perduokite ją per rekvizitus
Tada patikrinkite, kiek kartų bus iškviesta funkcija "Effect Hook", įtraukus šią funkciją į priklausomybių masyvą:
/// Vaikas
useEffect(() => {
console.log("getSquaredValue", getSquaredValue());
}, [getSquaredValue]);
Kiekvieno atvaizdavimo metu jis bus įrašytas į konsolę! Net jei reikšmės, esančios getSquaredValue() funkcija nepasikeitė. Tačiau galime to išvengti, jei šią funkciją apimsime funkcija useCallback
Jis nėra neutralus vertinant išteklių sąnaudas - "useMemo" turi būti iškviečiamas kiekvieno atvaizdavimo metu, išsaugo vertę atmintyje ir ją palygina (pridėtinės atminties sąnaudos),
naudoja "Memoization" - optimizavimo techniką, specifinę spartinančiosios atminties formą.
Jį turėtumėte naudoti tik dviem atvejais:
Jei norite išvengti sudėtingo kodo iškvietimo kiekvieno atvaizdavimo metu;
Jei norite pasiekti nuorodų lygybę.
Pažvelkime šiek tiek atidžiau į antrąjį atvejį. Norime naudoti useEffect su priklausomu objektu. Kadangi objektai lyginami pagal nuorodą, useEffect bus iškviečiamas kiekvieno atvaizdavimo metu. Kad išvengtume tokių dalykų, galime sujungti useEffect su useMemo, kad tokius objektus pamatytume, o tada šiuos pamatytuosius objektus perduotume į priklausomybių masyvą. Trumpas pavyzdys:
Dėl objekto 'hobbit' kiekvieno atvaizdavimo metu keičiasi 'useEffect Hook' (49 eilutė) priklausomybės. Perkelkite jį į "useEffect" grįžtamojo skambučio vidų. Arba inicializuokite 'hobbit' objektą jo paties useMemo () kabliuku.eslintreact-hooks/exhaustive-deps
Svarbiausias dalykas: useRef nesukelia pakartotinio atvaizdavimo (kaip useState), nes nėra susijęs su atvaizdavimo ciklu - jis išlaiko tą pačią nuorodą tarp atvaizdavimų.
const ref = useRef(0);
Norėdami iškviesti išsaugotą vertę, turite naudoti dabartinę savybę (ref yra objektas) - ref.current
Antrasis atvejis, kai galime naudoti šį kabliuką, yra nuoroda į elementus HTML viduje. Kiekvienas elementas turi atributą ref. Taigi, galime tvarkyti fokusavimą, įvykius ir t. t.
Trečiuoju atveju galime naudoti nuorodas, kad tvarkytume nekontroliuojamus komponentus. Daugiau apie juos galite paskaityti react dokumentai, bet trumpai tariant, tai atrodo taip:
Kaip matote, nėra jokio įvykio tvarkyklės, ji tiesiog įsimena įvestą reikšmę. Tai puikiai tinka pagrindinėms formoms tvarkyti, kai norite tik perskaityti išsaugotas reikšmes, kai jų reikia (pvz., pateikiant).
Priedas: tai puiku, kai reikia prisiminti ankstesnes būsenos vertes. Galite naudoti useEffect kabliuką, tiesiog perduokite būseną į ref.
Kaip matote, kabliukai nėra tokie akivaizdūs. Juos galime derinti ir taip išspręsti daugybę problemų. Išstudijavę šią temą tikrai turėsite daug naudos.
Taip pat yra pasirinktinių kabliukų...
Apibendrinant, React kabliukai iš esmės pakeitė React kūrėjai požiūris į pastatą žiniatinklio svetainė programos . Suteikdami intuityvesnį ir efektyvesnį būdą valdyti funkcinių komponentų būseną ir gyvavimo ciklą, kabliukai tapo neatsiejama React kūrimas.
Nesvarbu, ar esate patyręs kūrėjas, ar tik pradedate dirbti su React, labai svarbu išmanyti populiariausius kabliukus ir jų naudojimo atvejus. Naudodami tokias kabutes kaip useState, useEffect, useContext ir kt, React komponentai galima sukurti švaresnį ir daugkartinio naudojimo kodą. Be to, galimybė kurti pasirinktiniai kabliukai kūrėjams suteikiama galimybė apjungti ir bendrinti logiką keliuose komponentuose, taip skatinant pakartotinį kodo panaudojimą ir moduliarumą. Kadangi React ir toliau tobulėja ir diegia naujas funkcijas, kabliukai neabejotinai atliks pagrindinį vaidmenį siekiant išnaudoti visas sistemos galimybes.
Nesvarbu, ar kuriate nedidelę funkcinę programėlę, ar didelės apimties žiniatinklio programėlę. React kabliukai patobulins jūsų kūrimo darbo eigą ir atvers daugybę galimybių kurti patikimus ir daugybę funkcijų turinčius React programos .