Õppige Reacti hook'ide komponeerimist keerulise loogika abstraheerimiseks, koodi taaskasutuse ja hooldatavuse parandamiseks. Sisaldab praktilisi näiteid ja parimaid praktikaid.
Reacti kohandatud hook'ide kompositsioon: keerulise loogika abstraktsiooni valdamine
Reacti kohandatud hook'id on võimas tööriist olekupõhise loogika kapseldamiseks ja taaskasutamiseks teie Reacti rakendustes. Kuid rakenduste keerukuse kasvades kasvab ka teie kohandatud hook'ide loogika. See võib viia monoliitsete hook'ideni, mida on raske mõista, testida ja hooldada. Kohandatud hook'ide kompositsioon pakub sellele probleemile lahenduse, võimaldades teil jagada keerulise loogika väiksemateks, paremini hallatavateks ja taaskasutatavateks hook'ideks.
Mis on kohandatud hook'ide kompositsioon?
Kohandatud hook'ide kompositsioon on praktika, kus mitu väiksemat kohandatud hook'i kombineeritakse keerukama funktsionaalsuse loomiseks. Selle asemel, et luua üks suur hook, mis tegeleb kõigega, loote mitu väiksemat hook'i, millest igaüks vastutab loogika kindla aspekti eest. Neid väiksemaid hook'e saab seejärel soovitud funktsionaalsuse saavutamiseks kokku komponeerida.
Mõelge sellest kui LEGO klotsidega ehitamisest. Igal klotsil (väikesel hook'il) on kindel funktsioon ja te kombineerite neid erinevatel viisidel, et ehitada keerulisi struktuure (suuremaid funktsioone).
Kohandatud hook'ide kompositsiooni eelised
- Parem koodi taaskasutatavus: Väiksemad, keskendunuma eesmärgiga hook'id on olemuslikult paremini taaskasutatavad erinevates komponentides ja isegi erinevates projektides.
- Parem hooldatavus: Keerulise loogika jaotamine väiksemateks, iseseisvateks üksusteks muudab koodi mõistmise, silumise ja muutmise lihtsamaks. Muudatused ühes hook'is mõjutavad vähem tõenäoliselt teie rakenduse teisi osi.
- Suurem testitavus: Väiksemaid hook'e on lihtsam eraldi testida, mis viib robustsema ja usaldusväärsema koodini.
- Parem koodi organiseeritus: Kompositsioon soodustab modulaarsemat ja organiseeritumat koodibaasi, muutes rakenduse erinevate osade vaheliste seoste navigeerimise ja mõistmise lihtsamaks.
- Vähendatud koodi dubleerimine: Ühise loogika eraldamisega taaskasutatavatesse hook'idesse minimeerite koodi dubleerimist, mis viib lühema ja paremini hooldatava koodibaasini.
Millal kasutada kohandatud hook'ide kompositsiooni
Te peaksite kaaluma kohandatud hook'ide kompositsiooni kasutamist, kui:
- Ăśks kohandatud hook on muutumas liiga suureks ja keeruliseks.
- Leiate end dubleerimas sarnast loogikat mitmes kohandatud hook'is või komponendis.
- Soovite parandada oma kohandatud hook'ide testitavust.
- Soovite luua modulaarsema ja taaskasutatavama koodibaasi.
Kohandatud hook'ide kompositsiooni põhiprintsiibid
Siin on mõned põhiprintsiibid, mis aitavad teil kohandatud hook'ide kompositsioonile läheneda:
- Ühe vastutuse printsiip: Igal kohandatud hook'il peaks olema üks, selgelt määratletud vastutus. See muudab nende mõistmise, testimise ja taaskasutamise lihtsamaks.
- Huvide eraldamine: Eraldage oma loogika erinevad aspektid erinevatesse hook'idesse. Näiteks võib teil olla üks hook andmete pärimiseks, teine oleku haldamiseks ja kolmas kõrvalmõjude käsitlemiseks.
- Kompositsioonivõime: Disainige oma hook'id nii, et neid saaks hõlpsasti teiste hook'idega komponeerida. See hõlmab sageli andmete või funktsioonide tagastamist, mida teised hook'id saavad kasutada.
- Nimekonventsioonid: Kasutage oma hook'idele selgeid ja kirjeldavaid nimesid, et näidata nende eesmärki ja funktsionaalsust. Levinud konventsioon on lisada hook'i nime ette eesliide `use`.
Levinud kompositsioonimustrid
Kohandatud hook'ide komponeerimiseks saab kasutada mitmeid mustreid. Siin on mõned kõige levinumad:
1. Lihtne hook'ide kompositsioon
See on kõige elementaarsem kompositsioonivorm, kus üks hook kutsub lihtsalt teise hook'i välja ja kasutab selle tagastatud väärtust.
Näide: Kujutage ette, et teil on hook kasutajaandmete pärimiseks ja teine kuupäevade vormindamiseks. Saate need hook'id komponeerida, et luua uus hook, mis pärib kasutajaandmed ja vormindab kasutaja registreerimiskuupäeva.
import { useState, useEffect } from 'react';
function useUserData(userId) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const jsonData = await response.json();
setData(jsonData);
} catch (e) {
setError(e);
} finally {
setLoading(false);
}
}
fetchData();
}, [userId]);
return { data, loading, error };
}
function useFormattedDate(dateString) {
try {
const date = new Date(dateString);
const formattedDate = date.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' });
return formattedDate;
} catch (error) {
console.error("Error formatting date:", error);
return "Invalid Date";
}
}
function useUserWithFormattedDate(userId) {
const { data, loading, error } = useUserData(userId);
const formattedRegistrationDate = data ? useFormattedDate(data.registrationDate) : null;
return { ...data, formattedRegistrationDate, loading, error };
}
export default useUserWithFormattedDate;
Selgitus:
useUserDatapärib kasutajaandmed API-st.useFormattedDatevormindab kuupäevastringi kasutajasõbralikku vormingusse. See käsitleb sujuvalt võimalikke kuupäeva parsimise vigu. Argument `undefined` funktsioonis `toLocaleDateString` kasutab vormindamiseks kasutaja lokaati.useUserWithFormattedDatekomponeerib mõlemad hook'id. Esmalt kasutab see kasutajaandmete pärimiseks hook'iuseUserData. Seejärel, kui andmed on saadaval, kasutab seeregistrationDatevormindamiseks hook'iuseFormattedDate. Lõpuks tagastab see algsed kasutajaandmed koos vormindatud kuupäeva, laadimise oleku ja võimalike vigadega.
2. Hook'ide kompositsioon jagatud olekuga
Selles mustris jagavad ja muudavad mitu hook'i sama olekut. Seda saab saavutada, kasutades useContext'i või edastades oleku- ja seadistusfunktsioone hook'ide vahel.
Näide: Kujutage ette mitmeastmelise vormi ehitamist. Igal sammul võiks olla oma hook, et hallata selle sammu spetsiifilisi sisestusvälju ja valideerimisloogikat, kuid nad kõik jagavad ühist vormi olekut, mida haldab vanem-hook, kasutades useReducer'it ja useContext'i.
import React, { createContext, useContext, useReducer } from 'react';
// Määrake algolek
const initialState = {
step: 1,
name: '',
email: '',
address: ''
};
// Määrake tegevused
const ACTIONS = {
NEXT_STEP: 'NEXT_STEP',
PREVIOUS_STEP: 'PREVIOUS_STEP',
UPDATE_FIELD: 'UPDATE_FIELD'
};
// Looge reduktor
function formReducer(state, action) {
switch (action.type) {
case ACTIONS.NEXT_STEP:
return { ...state, step: state.step + 1 };
case ACTIONS.PREVIOUS_STEP:
return { ...state, step: state.step - 1 };
case ACTIONS.UPDATE_FIELD:
return { ...state, [action.payload.field]: action.payload.value };
default:
return state;
}
}
// Looge kontekst
const FormContext = createContext();
// Looge provider-komponent
function FormProvider({ children }) {
const [state, dispatch] = useReducer(formReducer, initialState);
const value = {
state,
dispatch,
nextStep: () => dispatch({ type: ACTIONS.NEXT_STEP }),
previousStep: () => dispatch({ type: ACTIONS.PREVIOUS_STEP }),
updateField: (field, value) => dispatch({ type: ACTIONS.UPDATE_FIELD, payload: { field, value } })
};
return (
{children}
);
}
// Kohandatud hook vormi kontekstile juurdepääsemiseks
function useFormContext() {
const context = useContext(FormContext);
if (!context) {
throw new Error('useFormContext must be used within a FormProvider');
}
return context;
}
// Kohandatud hook 1. sammu jaoks
function useStep1() {
const { state, updateField } = useFormContext();
const updateName = (value) => updateField('name', value);
return {
name: state.name,
updateName
};
}
// Kohandatud hook 2. sammu jaoks
function useStep2() {
const { state, updateField } = useFormContext();
const updateEmail = (value) => updateField('email', value);
return {
email: state.email,
updateEmail
};
}
// Kohandatud hook 3. sammu jaoks
function useStep3() {
const { state, updateField } = useFormContext();
const updateAddress = (value) => updateField('address', value);
return {
address: state.address,
updateAddress
};
}
export { FormProvider, useFormContext, useStep1, useStep2, useStep3 };
Selgitus:
- Vormi oleku ja dispatch-funktsiooni hoidmiseks luuakse
FormContext, kasutadescreateContext'i. formReducerhaldab vormi oleku uuendusi, kasutadesuseReducer'it. Oleku muutmiseks on defineeritud tegevused naguNEXT_STEP,PREVIOUS_STEPjaUPDATE_FIELD.- Komponent
FormProviderpakub vormi konteksti oma lastele, muutes oleku ja dispatch-funktsiooni kättesaadavaks kõikidele vormi sammudele. Samuti pakub see abifunktsioonenextStep,previousStepjaupdateFieldjaoks, et lihtsustada tegevuste saatmist. - Hook
useFormContextvõimaldab komponentidel pääseda ligi vormi konteksti väärtustele. - Iga samm (
useStep1,useStep2,useStep3) loob oma hook'i, et hallata oma sammuga seotud sisendit ja kasutabuseFormContext'i, et saada olekut ja dispatch-funktsiooni selle uuendamiseks. Iga samm paljastab ainult selle sammu jaoks asjakohased andmed ja funktsioonid, järgides ühe vastutuse printsiipi.
3. Hook'ide kompositsioon elutsĂĽkli haldusega
See muster hõlmab hook'e, mis haldavad komponendi elutsükli erinevaid faase, nagu paigaldamine, uuendamine ja eemaldamine. See saavutatakse sageli useEffect'i kasutamisega komponeeritud hook'ides.
Näide: Kujutage ette komponenti, mis peab jälgima võrguühenduse olekut (online/offline) ja tegema ka eemaldamisel teatud puhastustoiminguid. Nende ülesannete jaoks saate luua eraldi hook'id ja need seejärel komponeerida.
import { useState, useEffect } from 'react';
function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(navigator.onLine);
useEffect(() => {
function handleOnline() {
setIsOnline(true);
}
function handleOffline() {
setIsOnline(false);
}
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, []);
return isOnline;
}
function useDocumentTitle(title) {
useEffect(() => {
document.title = title;
return () => {
document.title = 'Original Title'; // Taasta vaikimisi pealkiri eemaldamisel
};
}, [title]);
}
function useAppLifecycle(title) {
const isOnline = useOnlineStatus();
useDocumentTitle(title);
return isOnline; // Tagasta võrguühenduse olek
}
export { useAppLifecycle, useOnlineStatus, useDocumentTitle };
Selgitus:
useOnlineStatusjälgib kasutaja võrguühenduse olekut, kasutades sündmusionlinejaoffline. HookuseEffectseadistab sündmuste kuulajad komponendi paigaldamisel ja puhastab need eemaldamisel.useDocumentTitleuuendab dokumendi pealkirja. Samuti taastab see pealkirja vaikimisi väärtusele komponendi eemaldamisel, tagades, et ei teki püsivaid pealkirjaprobleeme.useAppLifecyclekomponeerib mõlemad hook'id. See kasutabuseOnlineStatus't, et teha kindlaks, kas kasutaja on võrgus, jauseDocumentTitle'i dokumendi pealkirja määramiseks. Kombineeritud hook tagastab võrguühenduse oleku.
Praktilised näited ja kasutusjuhud
1. Rahvusvahelistamine (i18n)
Tõlgete ja lokaatide vahetamise haldamine võib muutuda keeruliseks. Huvide eraldamiseks saate kasutada hook'ide kompositsiooni:
useLocale(): Haldab praegust lokaati.useTranslations(): Pärib ja pakub tõlkeid praeguse lokaadi jaoks.useTranslate(key): Hook, mis võtab tõlkevõtme ja tagastab tõlgitud stringi, kasutades tõlgetele juurdepääsemiseks hook'iuseTranslations.
See võimaldab teil hõlpsalt lokaate vahetada ja tõlgetele kogu rakenduses juurde pääseda. Kaaluge raamistike nagu i18next kasutamist koos kohandatud hook'idega tõlkeloogika haldamiseks. Näiteks võiks useTranslations laadida tõlkeid valitud lokaadi põhjal eri keeltes JSON-failidest.
2. Vormi valideerimine
Keerulised vormid nõuavad sageli ulatuslikku valideerimist. Taaskasutatava valideerimisloogika loomiseks saate kasutada hook'ide kompositsiooni:
useInput(initialValue): Haldab ühe sisestusvälja olekut.useValidator(value, rules): Valideerib ühe sisestusvälja reeglite kogumi alusel (nt nõutud, e-post, minLength).useForm(fields): Haldab kogu vormi olekut ja valideerimist, komponeerides iga välja jaoksuseInput'i jauseValidator'it.
See lähenemine soodustab koodi taaskasutatavust ja muudab valideerimisreeglite lisamise või muutmise lihtsamaks. Raamatukogud nagu Formik või React Hook Form pakuvad valmislahendusi, kuid neid saab täiendada kohandatud hook'idega spetsiifiliste valideerimisvajaduste jaoks.
3. Andmete pärimine ja vahemällu salvestamine
Andmete pärimise, vahemällu salvestamise ja veahalduse haldamist saab lihtsustada hook'ide kompositsiooniga:
useFetch(url): Pärib andmeid antud URL-ilt.useCache(key, fetchFunction): Salvestab pärimisfunktsiooni tulemuse vahemällu, kasutades võtit.useData(url, options): KombineeribuseFetch'i jauseCache'i andmete pärimiseks ja tulemuste vahemällu salvestamiseks.
See võimaldab teil hõlpsasti vahemällu salvestada sageli kasutatavaid andmeid ja parandada jõudlust. Raamatukogud nagu SWR (Stale-While-Revalidate) ja React Query pakuvad võimsaid andmete pärimise ja vahemällu salvestamise lahendusi, mida saab laiendada kohandatud hook'idega.
4. Autentimine
Autentimisloogika käsitlemine võib olla keeruline, eriti kui tegemist on erinevate autentimismeetoditega (nt JWT, OAuth). Hook'ide kompositsioon aitab eraldada autentimisprotsessi erinevaid aspekte:
useAuthToken(): Haldab autentimistõendit (nt selle salvestamine ja pärimine kohalikust mälust).useUser(): Pärib ja pakub praeguse kasutaja teavet autentimistõendi alusel.useAuth(): Pakub autentimisega seotud funktsioone nagu sisselogimine, väljalogimine ja registreerumine, komponeerides teisi hook'e.
See lähenemine võimaldab teil hõlpsalt vahetada erinevate autentimismeetodite vahel või lisada autentimisprotsessile uusi funktsioone. Kasutajakontode ja autentimise haldamiseks võib taustaprogrammina kasutada raamatukogusid nagu Auth0 ja Firebase Authentication ning nende teenustega suhtlemiseks saab luua kohandatud hook'e.
Parimad praktikad kohandatud hook'ide kompositsiooniks
- Hoidke hook'id keskendununa: Igal hook'il peaks olema selge ja konkreetne eesmärk.
- Vältige sügavat pesastamist: Piirake kompositsioonitasemete arvu, et vältida koodi raskesti mõistetavaks muutmist. Kui hook muutub liiga keeruliseks, kaaluge selle edasist jaotamist.
- Dokumenteerige oma hook'id: Pakkuge iga hook'i jaoks selget ja lühikest dokumentatsiooni, selgitades selle eesmärki, sisendeid ja väljundeid. See on eriti oluline hook'ide puhul, mida kasutavad teised arendajad.
- Testige oma hook'e: Kirjutage iga hook'i jaoks ühiktestid, et tagada selle korrektne toimimine. See on eriti oluline hook'ide puhul, mis haldavad olekut või teostavad kõrvalmõjusid.
- Kaaluge olekuhaldusraamistiku kasutamist: Keeruliste olekuhaldusstsenaariumide korral kaaluge raamistiku nagu Redux, Zustand või Jotai kasutamist. Need raamatukogud pakuvad täpsemaid funktsioone oleku haldamiseks ja võivad lihtsustada hook'ide komponeerimist.
- Mõelge veahaldusele: Rakendage oma hook'ides robustset veahaldust, et vältida ootamatut käitumist. Kaaluge try-catch plokkide kasutamist vigade püüdmiseks ja informatiivsete veateadete pakkumiseks.
- Kaaluge jõudlust: Olge teadlik oma hook'ide jõudlusmõjudest. Vältige tarbetuid uuesti renderdamisi ja optimeerige oma koodi jõudluse parandamiseks. Kasutage jõudluse optimeerimiseks vajadusel React.memo, useMemo ja useCallback.
Kokkuvõte
Reacti kohandatud hook'ide kompositsioon on võimas tehnika keerulise loogika abstraheerimiseks ning koodi taaskasutatavuse, hooldatavuse ja testitavuse parandamiseks. Jagades keerulised ülesanded väiksemateks, paremini hallatavateks hook'ideks, saate luua modulaarsema ja organiseerituma koodibaasi. Järgides selles artiklis kirjeldatud parimaid praktikaid, saate tõhusalt kasutada kohandatud hook'ide kompositsiooni robustsete ja skaleeritavate Reacti rakenduste ehitamiseks. Pidage meeles, et alati tuleb oma koodis eelistada selgust ja lihtsust ning ärge kartke katsetada erinevaid kompositsioonimustreid, et leida, mis sobib teie konkreetsetele vajadustele kõige paremini.