Atskleiskite daugkartinio naudojimo logikos galią savo „React“ programose su pasirinktiniais kabliukais. Sužinokite, kaip juos kurti ir naudoti švaresniam kodui.
Pasirinktiniai kabliukai (Custom Hooks): Daugkartinio naudojimo logikos šablonai „React“
„React“ kabliukai (Hooks) sukėlė revoliuciją funkcinių komponentų rašymo būde, įdiegdami būsenos ir gyvavimo ciklo funkcijas. Tarp daugybės jų teikiamų privalumų, pasirinktiniai kabliukai išsiskiria kaip galingas mechanizmas logikai išgauti ir pakartotinai naudoti keliuose komponentuose. Šiame tinklaraščio įraše pasinersime į pasirinktinių kabliukų pasaulį, nagrinėsime jų privalumus, kūrimą ir naudojimą su praktiniais pavyzdžiais.
Kas yra pasirinktiniai kabliukai?
Iš esmės, pasirinktinis kabliukas (custom hook) yra „JavaScript“ funkcija, kuri prasideda žodžiu „use“ ir gali kviesti kitus kabliukus. Jie leidžia iškelti komponento logiką į daugkartinio naudojimo funkcijas. Tai galingas būdas dalytis būseną turinčia logika, šalutiniais poveikiais ar kitokiu sudėtingu elgesiu tarp komponentų, nesinaudojant atvaizdavimo savybėmis (render props), aukštesnės eilės komponentais (higher-order components) ar kitais sudėtingais šablonais.
Pagrindinės pasirinktinių kabliukų savybės:
- Pavadinimų taisyklė: Pasirinktiniai kabliukai turi prasidėti žodžiu „use“. Tai signalizuoja „React“, kad funkcija turi kabliukų ir turėtų laikytis kabliukų taisyklių.
- Daugkartinis naudojimas: Pagrindinis tikslas yra inkapsuliuoti daugkartinio naudojimo logiką, kad būtų lengva dalytis funkcionalumu tarp komponentų.
- Būsenos logika: Pasirinktiniai kabliukai gali valdyti savo būseną naudodami
useState
kabliuką, leidžiantį jiems inkapsuliuoti sudėtingą būsenos elgesį. - Šalutiniai poveikiai: Jie taip pat gali atlikti šalutinius poveikius naudodami
useEffect
kabliuką, suteikdami galimybę integruotis su išorinėmis API, gauti duomenis ir kt. - Komponuojamumas: Pasirinktiniai kabliukai gali kviesti kitus kabliukus, leidžiant kurti sudėtingą logiką, sujungiant mažesnius, labiau specializuotus kabliukus.
Pasirinktinių kabliukų naudojimo privalumai
Pasirinktiniai kabliukai siūlo keletą reikšmingų privalumų „React“ kūrime:
- Kodo daugkartinis naudojimas: Akivaizdžiausias privalumas yra galimybė pakartotinai naudoti logiką keliuose komponentuose. Tai sumažina kodo dubliavimą ir skatina DRY (nesikartok) principo taikymą kodo bazėje.
- Pagerintas skaitomumas: Iškėlus sudėtingą logiką į atskirus pasirinktinius kabliukus, jūsų komponentai tampa švaresni ir lengviau suprantami. Pagrindinė komponento logika lieka sutelkta į vartotojo sąsajos atvaizdavimą.
- Patobulintas palaikymas: Kai logika yra inkapsuliuota pasirinktiniuose kabliukuose, pakeitimus ir klaidų taisymus galima atlikti vienoje vietoje, sumažinant klaidų įvedimo riziką keliuose komponentuose.
- Testuojamumas: Pasirinktinius kabliukus galima lengvai testuoti atskirai, užtikrinant, kad daugkartinio naudojimo logika veiktų teisingai, nepriklausomai nuo ją naudojančių komponentų.
- Supaprastinti komponentai: Pasirinktiniai kabliukai padeda išvalyti komponentus, padarydami juos mažiau išsamiais ir labiau sutelktais į savo pagrindinį tikslą.
Pirmojo pasirinktinio kabliuko kūrimas
Iliustruokime pasirinktinio kabliuko kūrimą praktiniu pavyzdžiu: kabliuku, kuris seka lango dydį.
Pavyzdys: useWindowSize
Šis kabliukas grąžins dabartinį naršyklės lango plotį ir aukštį. Jis taip pat atnaujins šias vertes, kai lango dydis bus pakeistas.
import { useState, useEffect } from 'react';
function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
function handleResize() {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
window.addEventListener('resize', handleResize);
// Išvalant pašalinti įvykio klausytoją
return () => window.removeEventListener('resize', handleResize);
}, []); // Tuščias masyvas užtikrina, kad efektas bus paleistas tik prijungus komponentą
return windowSize;
}
export default useWindowSize;
Paaiškinimas:
- Būtinų kabliukų importavimas: Importuojame
useState
iruseEffect
iš „React“. - Kabliuko apibrėžimas: Sukuriame funkciją pavadinimu
useWindowSize
, laikydamiesi pavadinimų taisyklės. - Būsenos inicializavimas: Naudojame
useState
, kad inicializuotumewindowSize
būseną su pradiniu lango pločiu ir aukščiu. - Įvykio klausytojo nustatymas: Naudojame
useEffect
, kad pridėtume dydžio keitimo įvykio klausytoją prie lango. Kai lango dydis pasikeičia,handleResize
funkcija atnaujinawindowSize
būseną. - Išvalymas: Grąžiname išvalymo funkciją iš
useEffect
, kad pašalintume įvykio klausytoją, kai komponentas atsijungia. Tai apsaugo nuo atminties nutekėjimo. - Reikšmių grąžinimas: Kabliukas grąžina
windowSize
objektą, kuriame yra dabartinis lango plotis ir aukštis.
Pasirinktinio kabliuko naudojimas komponente
Dabar, kai sukūrėme savo pasirinktinį kabliuką, pažiūrėkime, kaip jį naudoti „React“ komponente.
import React from 'react';
import useWindowSize from './useWindowSize';
function MyComponent() {
const { width, height } = useWindowSize();
return (
Lango plotis: {width}px
Lango aukštis: {height}px
);
}
export default MyComponent;
Paaiškinimas:
- Kabliuko importavimas: Importuojame
useWindowSize
pasirinktinį kabliuką. - Kabliuko kvietimas: Kviesime
useWindowSize
kabliuką komponente. - Prieiga prie reikšmių: Išskleidžiame grąžintą objektą, kad gautume
width
irheight
reikšmes. - Reikšmių atvaizdavimas: Atvaizduojame pločio ir aukščio reikšmes komponento vartotojo sąsajoje.
Bet kuris komponentas, naudojantis useWindowSize
, automatiškai atsinaujins, pasikeitus lango dydžiui.
Sudėtingesni pavyzdžiai
Panagrinėkime keletą pažangesnių pasirinktinių kabliukų naudojimo atvejų.
Pavyzdys: useLocalStorage
Šis kabliukas leidžia lengvai saugoti ir gauti duomenis iš vietinės saugyklos (local storage).
import { useState, useEffect } from 'react';
function useLocalStorage(key, initialValue) {
// Būsena mūsų reikšmei saugoti
// Perduodame pradinę reikšmę į useState, kad logika būtų vykdoma tik vieną kartą
const [storedValue, setStoredValue] = useState(() => {
try {
// Gauname iš vietinės saugyklos pagal raktą
const item = window.localStorage.getItem(key);
// Analizuojame saugomą json arba, jei jo nėra, grąžiname pradinę reikšmę
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// Jei įvyko klaida, taip pat grąžiname pradinę reikšmę
console.log(error);
return initialValue;
}
});
// Grąžiname apgaubtą useState nustatymo funkcijos versiją, kuri...
// ... išsaugo naują reikšmę localStorage.
const setValue = (value) => {
try {
// Leidžiame reikšmei būti funkcija, kad turėtume tą patį API kaip useState
const valueToStore = value instanceof Function ? value(storedValue) : value;
// Išsaugome vietinėje saugykloje
window.localStorage.setItem(key, JSON.stringify(valueToStore));
// Išsaugome būseną
setStoredValue(valueToStore);
} catch (error) {
// Pažangesnis įgyvendinimas apdorotų klaidos atvejį
console.log(error);
}
};
useEffect(() => {
try {
const item = window.localStorage.getItem(key);
setStoredValue(item ? JSON.parse(item) : initialValue);
} catch (error) {
console.log(error);
}
}, [key, initialValue]);
return [storedValue, setValue];
}
export default useLocalStorage;
Naudojimas:
import React from 'react';
import useLocalStorage from './useLocalStorage';
function MyComponent() {
const [name, setName] = useLocalStorage('name', 'Svečias');
return (
Sveiki, {name}!
setName(e.target.value)}
/>
);
}
export default MyComponent;
Pavyzdys: useFetch
Šis kabliukas inkapsuliuoja duomenų gavimo iš API logiką.
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP klaida! būsena: ${response.status}`);
}
const json = await response.json();
setData(json);
setLoading(false);
} catch (error) {
setError(error);
setLoading(false);
}
}
fetchData();
}, [url]);
return { data, loading, error };
}
export default useFetch;
Naudojimas:
import React from 'react';
import useFetch from './useFetch';
function MyComponent() {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos/1');
if (loading) return Kraunama...
;
if (error) return Klaida: {error.message}
;
return (
Pavadinimas: {data.title}
Užbaigta: {data.completed ? 'Taip' : 'Ne'}
);
}
export default MyComponent;
Geriausios pasirinktinių kabliukų praktikos
Kad jūsų pasirinktiniai kabliukai būtų veiksmingi ir lengvai palaikomi, laikykitės šių geriausių praktikų:
- Išlaikykite juos specializuotus: Kiekvienas pasirinktinis kabliukas turėtų turėti vieną, gerai apibrėžtą paskirtį. Venkite kurti pernelyg sudėtingus kabliukus, kurie bando daryti per daug.
- Dokumentuokite savo kabliukus: Pateikite aiškią ir glaustą dokumentaciją kiekvienam pasirinktiniam kabliukui, paaiškindami jo paskirtį, įvesties ir išvesties duomenis.
- Testuokite savo kabliukus: Rašykite vienetinius testus savo pasirinktiniams kabliukams, kad užtikrintumėte, jog jie veikia teisingai ir patikimai.
- Naudokite aprašomuosius pavadinimus: Rinkitės aprašomuosius pavadinimus savo pasirinktiniams kabliukams, kurie aiškiai nurodo jų paskirtį.
- Elegantiškai tvarkykite klaidas: Įdiekite klaidų tvarkymą savo pasirinktiniuose kabliukuose, kad išvengtumėte netikėto elgesio ir pateiktumėte informatyvius klaidų pranešimus.
- Apsvarstykite daugkartinį naudojimą: Kurkite savo pasirinktinius kabliukus atsižvelgdami į daugkartinį naudojimą. Padarykite juos pakankamai bendrus, kad juos būtų galima naudoti keliuose komponentuose.
- Venkite per didelės abstrakcijos: Nekurkite pasirinktinių kabliukų paprastai logikai, kurią galima lengvai tvarkyti komponente. Iškelkite tik tą logiką, kuri yra tikrai daugkartinio naudojimo ir sudėtinga.
Dažniausios klaidos, kurių reikia vengti
- Kabliukų taisyklių pažeidimas: Visada kvieskite kabliukus aukščiausiame savo pasirinktinio kabliuko funkcijos lygmenyje ir kvieskite juos tik iš „React“ funkcinių komponentų ar kitų pasirinktinių kabliukų.
- Priklausomybių ignoravimas „useEffect“: Įsitikinkite, kad įtraukėte visas būtinas priklausomybes į
useEffect
kabliuko priklausomybių masyvą, kad išvengtumėte pasenusių uždarymų (stale closures) ir netikėto elgesio. - Begalinų ciklų kūrimas: Būkite atsargūs atnaujindami būseną
useEffect
kabliuke, nes tai gali lengvai sukelti begalinius ciklus. Užtikrinkite, kad atnaujinimas būtų sąlyginis ir priklausytų nuo priklausomybių pokyčių. - Užmirštas išvalymas: Visada įtraukite išvalymo funkciją į
useEffect
, kad pašalintumėte įvykių klausytojus, atšauktumėte prenumeratas ir atliktumėte kitas išvalymo užduotis, siekiant išvengti atminties nutekėjimo.
Pažangūs šablonai
Pasirinktinių kabliukų komponavimas
Pasirinktinius kabliukus galima komponuoti kartu, norint sukurti sudėtingesnę logiką. Pavyzdžiui, galite sujungti useLocalStorage
kabliuką su useFetch
kabliuku, kad automatiškai išsaugotumėte gautus duomenis vietinėje saugykloje.
Logikos dalijimasis tarp kabliukų
Jei keli pasirinktiniai kabliukai dalijasi bendra logika, galite iškelti tą logiką į atskirą pagalbinę funkciją ir pakartotinai ją naudoti abiejuose kabliukuose.
Konteksto (Context) naudojimas su pasirinktiniais kabliukais
Pasirinktiniai kabliukai gali būti naudojami kartu su „React“ kontekstu (Context), norint pasiekti ir atnaujinti globalią būseną. Tai leidžia kurti daugkartinio naudojimo komponentus, kurie žino apie programos globalią būseną ir gali su ja sąveikauti.
Pavyzdžiai iš realaus pasaulio
Štai keletas pavyzdžių, kaip pasirinktiniai kabliukai gali būti naudojami realiose programose:
- Formos patvirtinimas: Sukurkite
useForm
kabliuką, kuris tvarkytų formos būseną, patvirtinimą ir pateikimą. - Autentifikavimas: Įgyvendinkite
useAuth
kabliuką, kuris valdytų vartotojo autentifikavimą ir autorizavimą. - Temos valdymas: Sukurkite
useTheme
kabliuką, skirtą perjungti skirtingas temas (šviesią, tamsią ir kt.). - Geolokacija: Sukurkite
useGeolocation
kabliuką, kuris sektų vartotojo dabartinę buvimo vietą. - Slinkties aptikimas: Sukurkite
useScroll
kabliuką, kuris aptiktų, kada vartotojas paslinko iki tam tikro taško puslapyje.
Pavyzdys: useGeolocation kabliukas tarpkultūrinėms programoms, tokioms kaip žemėlapių ar pristatymo paslaugos
import { useState, useEffect } from 'react';
function useGeolocation() {
const [location, setLocation] = useState({
latitude: null,
longitude: null,
error: null,
});
useEffect(() => {
if (!navigator.geolocation) {
setLocation({
latitude: null,
longitude: null,
error: 'Ši naršyklė nepalaiko geolokacijos.',
});
return;
}
const watchId = navigator.geolocation.watchPosition(
(position) => {
setLocation({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
});
},
(error) => {
setLocation({
latitude: null,
longitude: null,
error: error.message,
});
}
);
return () => navigator.geolocation.clearWatch(watchId);
}, []);
return location;
}
export default useGeolocation;
Išvada
Pasirinktiniai kabliukai yra galingas įrankis rašyti švaresnį, labiau daugkartinio naudojimo ir lengviau palaikomą „React“ kodą. Inkapsuliuodami sudėtingą logiką į pasirinktinius kabliukus, galite supaprastinti savo komponentus, sumažinti kodo dubliavimą ir pagerinti bendrą savo programų struktūrą. Pasinaudokite pasirinktiniais kabliukais ir atskleiskite jų potencialą kurti tvirtesnes ir labiau mastelio keitimui pritaikytas „React“ programas.
Pradėkite nuo sričių savo esamoje kodo bazėje, kur logika kartojasi keliuose komponentuose. Tada pertvarkykite tą logiką į pasirinktinius kabliukus. Laikui bėgant, sukursite daugkartinio naudojimo kabliukų biblioteką, kuri pagreitins jūsų kūrimo procesą ir pagerins jūsų kodo kokybę.
Nepamirškite laikytis geriausių praktikų, vengti dažniausių klaidų ir tyrinėti pažangius šablonus, kad maksimaliai išnaudotumėte pasirinktinius kabliukus. Su praktika ir patirtimi tapsite pasirinktinių kabliukų meistru ir efektyvesniu „React“ kūrėju.