Vapauta uudelleenkäytettävän logiikan voima React-sovelluksissasi kustomoiduilla koukuilla. Opi luomaan ja hyödyntämään niitä puhtaamman ja ylläpidettävämmän koodin aikaansaamiseksi.
Kustomoidut koukut: Uudelleenkäytettävät logiikkamallit Reactissa
React-koukut mullistivat tavan, jolla kirjoitamme React-komponentteja, tuomalla tilan ja elinkaariominaisuudet funktionaalisiin komponentteihin. Niiden monista eduista kustomoidut koukut erottuvat voimakkaana mekanismina logiikan poimimiseen ja uudelleenkäyttöön useiden komponenttien välillä. Tämä blogikirjoitus sukeltaa syvälle kustomoitujen koukkujen maailmaan, tutkien niiden etuja, luomista ja käyttöä käytännön esimerkkien avulla.
Mitä ovat kustomoidut koukut?
Pohjimmiltaan kustomoitu koukku on JavaScript-funktio, joka alkaa sanalla "use" ja voi kutsua muita koukkuja. Ne mahdollistavat komponenttilogiikan poimimisen uudelleenkäytettäviin funktioihin. Tämä on tehokas tapa jakaa tilallista logiikkaa, sivuvaikutuksia tai muita monimutkaisia toimintoja komponenttien välillä turvautumatta render props -malleihin, korkeamman asteen komponentteihin tai muihin monimutkaisiin malleihin.
Kustomoitujen koukkujen tärkeimmät ominaisuudet:
- Nimeämiskäytäntö: Kustomoitujen koukkujen on alettava sanalla "use". Tämä viestii Reactille, että funktio sisältää koukkuja ja sen tulee noudattaa koukkujen sääntöjä.
- Uudelleenkäytettävyys: Ensisijainen tarkoitus on kapseloida uudelleenkäytettävää logiikkaa, mikä tekee toiminnallisuuden jakamisesta komponenttien välillä helppoa.
- Tilallinen logiikka: Kustomoidut koukut voivat hallita omaa tilaansa käyttämällä
useState
-koukkua, mikä mahdollistaa monimutkaisen tilallisen toiminnan kapseloinnin. - Sivuvaikutukset: Ne voivat myös suorittaa sivuvaikutuksia käyttämällä
useEffect
-koukkua, mikä mahdollistaa integroinnin ulkoisiin API-rajapintoihin, datan noutoon ja muuhun. - Yhdisteltävyys: Kustomoidut koukut voivat kutsua muita koukkuja, mikä mahdollistaa monimutkaisen logiikan rakentamisen yhdistelemällä pienempiä, tarkemmin kohdennettuja koukkuja.
Kustomoitujen koukkujen käytön edut
Kustomoidut koukut tarjoavat useita merkittäviä etuja React-kehityksessä:
- Koodin uudelleenkäytettävyys: Ilmeisin etu on kyky uudelleenkäyttää logiikkaa useiden komponenttien välillä. Tämä vähentää koodin päällekkäisyyttä ja edistää DRY (Don't Repeat Yourself) -periaatteen mukaista koodikantaa.
- Parannettu luettavuus: Poimimalla monimutkaisen logiikan erillisiin kustomoituihin koukkuihin, komponenteistasi tulee siistimpiä ja helpommin ymmärrettäviä. Komponentin ydinlogiikka pysyy keskittyneenä käyttöliittymän renderöintiin.
- Parempi ylläpidettävyys: Kun logiikka on kapseloitu kustomoituihin koukkuihin, muutokset ja virheenkorjaukset voidaan tehdä yhdessä paikassa, mikä vähentää virheiden riskiä useissa komponenteissa.
- Testattavuus: Kustomoituja koukkuja voidaan helposti testata erikseen, mikä varmistaa, että uudelleenkäytettävä logiikka toimii oikein riippumatta sitä käyttävistä komponenteista.
- Yksinkertaistetut komponentit: Kustomoidut koukut auttavat siistimään komponentteja, tehden niistä vähemmän monisanaisia ja enemmän keskittyneitä niiden päätehtävään.
Ensimmäisen kustomoidun koukun luominen
Havainnollistetaan kustomoidun koukun luomista käytännön esimerkillä: koukulla, joka seuraa ikkunan kokoa.
Esimerkki: useWindowSize
Tämä koukku palauttaa selainikkunan nykyisen leveyden ja korkeuden. Se päivittää myös nämä arvot, kun ikkunan kokoa muutetaan.
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);
// Poista tapahtumankuuntelija siivouksen yhteydessä
return () => window.removeEventListener('resize', handleResize);
}, []); // Tyhjä taulukko varmistaa, että efekti suoritetaan vain komponentin liittämisen yhteydessä
return windowSize;
}
export default useWindowSize;
Selitys:
- Tarvittavien koukkujen tuonti: Tuomme
useState
jauseEffect
Reactista. - Koukun määrittely: Luomme funktion nimeltä
useWindowSize
, nimeämiskäytännön mukaisesti. - Tilan alustaminen: Käytämme
useState
-koukkua alustaaksemmewindowSize
-tilan ikkunan alkuperäisellä leveydellä ja korkeudella. - Tapahtumankuuntelijan asettaminen: Käytämme
useEffect
-koukkua lisätäksemme resize-tapahtumankuuntelijan ikkunaan. Kun ikkunan kokoa muutetaan,handleResize
-funktio päivittääwindowSize
-tilan. - Siivous: Palautamme siivousfunktion
useEffect
-koukusta poistaaksemme tapahtumankuuntelijan, kun komponentti poistetaan näkyvistä. Tämä estää muistivuotoja. - Arvojen palautus: Koukku palauttaa
windowSize
-olion, joka sisältää ikkunan nykyisen leveyden ja korkeuden.
Kustomoidun koukun käyttäminen komponentissa
Nyt kun olemme luoneet kustomoidun koukkumme, katsotaan, miten sitä käytetään React-komponentissa.
import React from 'react';
import useWindowSize from './useWindowSize';
function MyComponent() {
const { width, height } = useWindowSize();
return (
Ikkunan leveys: {width}px
Ikkunan korkeus: {height}px
);
}
export default MyComponent;
Selitys:
- Koukun tuonti: Tuomme
useWindowSize
-kustomoidun koukun. - Koukun kutsuminen: Kutsumme
useWindowSize
-koukkua komponentin sisällä. - Arvojen käyttö: Puramme palautetun olion saadaksemme
width
- jaheight
-arvot. - Arvojen renderöinti: Renderöimme leveys- ja korkeusarvot komponentin käyttöliittymässä.
Jokainen komponentti, joka käyttää useWindowSize
-koukkua, päivittyy automaattisesti, kun ikkunan koko muuttuu.
Monimutkaisempia esimerkkejä
Tutkitaan joitakin edistyneempiä käyttötapauksia kustomoiduille koukuille.
Esimerkki: useLocalStorage
Tämä koukku mahdollistaa datan helpon tallentamisen ja noutamisen paikallisesta tallennustilasta (local storage).
import { useState, useEffect } from 'react';
function useLocalStorage(key, initialValue) {
// Tila arvon tallentamiseen
// Välitä alkuarvo useState-koukulle, jotta logiikka suoritetaan vain kerran
const [storedValue, setStoredValue] = useState(() => {
try {
// Hae paikallisesta tallennustilasta avaimella
const item = window.localStorage.getItem(key);
// Jäsennä tallennettu JSON tai palauta alkuarvo, jos sitä ei ole
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// Jos virhe, palauta myös alkuarvo
console.log(error);
return initialValue;
}
});
// Palauta kääritty versio useStaten asetusfunktiosta, joka ...
// ... tallentaa uuden arvon pysyvästi localStorageen.
const setValue = (value) => {
try {
// Salli arvon olla funktio, jotta meillä on sama API kuin useState-koukulla
const valueToStore = value instanceof Function ? value(storedValue) : value;
// Tallenna paikalliseen tallennustilaan
window.localStorage.setItem(key, JSON.stringify(valueToStore));
// Tallenna tila
setStoredValue(valueToStore);
} catch (error) {
// Edistyneempi toteutus käsittelisi virhetilanteen
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;
Käyttö:
import React from 'react';
import useLocalStorage from './useLocalStorage';
function MyComponent() {
const [name, setName] = useLocalStorage('name', 'Vieras');
return (
Hei, {name}!
setName(e.target.value)}
/>
);
}
export default MyComponent;
Esimerkki: useFetch
Tämä koukku kapseloi logiikan datan noutamiseen API-rajapinnasta.
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-virhe! status: ${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;
Käyttö:
import React from 'react';
import useFetch from './useFetch';
function MyComponent() {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos/1');
if (loading) return Ladataan...
;
if (error) return Virhe: {error.message}
;
return (
Otsikko: {data.title}
Valmis: {data.completed ? 'Kyllä' : 'Ei'}
);
}
export default MyComponent;
Parhaat käytännöt kustomoiduille koukuille
Varmistaaksesi, että kustomoidut koukkusi ovat tehokkaita ja ylläpidettäviä, noudata näitä parhaita käytäntöjä:
- Pidä ne kohdennettuina: Jokaisella kustomoidulla koukulla tulisi olla yksi, selkeästi määritelty tarkoitus. Vältä luomasta liian monimutkaisia koukkuja, jotka yrittävät tehdä liikaa.
- Dokumentoi koukkusi: Tarjoa selkeä ja ytimekäs dokumentaatio jokaiselle kustomoidulle koukulle, selittäen sen tarkoituksen, syötteet ja tulosteet.
- Testaa koukkusi: Kirjoita yksikkötestit kustomoiduille koukuillesi varmistaaksesi, että ne toimivat oikein ja luotettavasti.
- Käytä kuvaavia nimiä: Valitse kustomoiduille koukuillesi kuvaavat nimet, jotka ilmaisevat selkeästi niiden tarkoituksen.
- Käsittele virheet sulavasti: Toteuta virheenkäsittely kustomoiduissa koukuissasi estääksesi odottamattoman käytöksen ja tarjotaksesi informatiivisia virheilmoituksia.
- Harkitse uudelleenkäytettävyyttä: Suunnittele kustomoidut koukkusi uudelleenkäytettävyyttä silmällä pitäen. Tee niistä riittävän yleisiä, jotta niitä voidaan käyttää useissa komponenteissa.
- Vältä yliabstrahointia: Älä luo kustomoituja koukkuja yksinkertaiselle logiikalle, joka voidaan helposti käsitellä komponentin sisällä. Poimi vain logiikka, joka on todella uudelleenkäytettävää ja monimutkaista.
Yleisimmät sudenkuopat vältettäväksi
- Koukkujen sääntöjen rikkominen: Aina kutsu koukkuja kustomoidun koukkufunktion ylätasolla ja vain kutsu niitä Reactin funktiokomponenteista tai muista kustomoiduista koukuista.
- Riippuvuuksien unohtaminen useEffect-koukusta: Varmista, että sisällytät kaikki tarvittavat riippuvuudet
useEffect
-koukun riippuvuustaulukkoon estääksesi vanhentuneita sulkeumia (stale closures) ja odottamattoman käytöksen. - Ikuisten silmukoiden luominen: Ole varovainen päivittäessäsi tilaa
useEffect
-koukun sisällä, sillä tämä voi helposti johtaa ikuisiin silmukoihin. Varmista, että päivitys on ehdollinen ja perustuu riippuvuuksien muutoksiin. - Siivouksen unohtaminen: Sisällytä aina siivousfunktio
useEffect
-koukkuun poistaaksesi tapahtumankuuntelijat, peruuttaaksesi tilaukset ja suorittaaksesi muita siivoustehtäviä muistivuotojen estämiseksi.
Edistyneet mallit
Kustomoitujen koukkujen yhdistely
Kustomoituja koukkuja voidaan yhdistellä toisiinsa monimutkaisemman logiikan luomiseksi. Voit esimerkiksi yhdistää useLocalStorage
-koukun useFetch
-koukkuun tallentaaksesi automaattisesti haetun datan paikalliseen tallennustilaan.
Logiikan jakaminen koukkujen välillä
Jos useat kustomoidut koukut jakavat yhteistä logiikkaa, voit poimia sen logiikan erilliseen aputoimintoon (utility function) ja käyttää sitä uudelleen molemmissa koukuissa.
Contextin käyttäminen kustomoitujen koukkujen kanssa
Kustomoituja koukkuja voidaan käyttää yhdessä React Contextin kanssa globaalin tilan käyttämiseen ja päivittämiseen. Tämä mahdollistaa uudelleenkäytettävien komponenttien luomisen, jotka ovat tietoisia sovelluksen globaalista tilasta ja voivat olla vuorovaikutuksessa sen kanssa.
Esimerkkejä todellisesta maailmasta
Tässä on joitain esimerkkejä siitä, miten kustomoituja koukkuja voidaan käyttää todellisissa sovelluksissa:
- Lomakkeen validointi: Luo
useForm
-koukku käsittelemään lomakkeen tilaa, validointia ja lähettämistä. - Autentikointi: Toteuta
useAuth
-koukku hallitsemaan käyttäjän autentikointia ja auktorisointia. - Teemanhallinta: Kehitä
useTheme
-koukku vaihtamaan eri teemojen välillä (vaalea, tumma jne.). - Geopaikannus: Rakenna
useGeolocation
-koukku seuraamaan käyttäjän nykyistä sijaintia. - Vierityksen tunnistus: Luo
useScroll
-koukku tunnistamaan, kun käyttäjä on vierittänyt tiettyyn kohtaan sivulla.
Esimerkki: useGeolocation-koukku monikulttuurisiin sovelluksiin, kuten kartta- tai toimituspalveluihin
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: 'Geopaikannusta ei tueta tässä selaimessa.',
});
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;
Yhteenveto
Kustomoidut koukut ovat tehokas työkalu puhtaamman, uudelleenkäytettävämmän ja ylläpidettävämmän React-koodin kirjoittamiseen. Kapseloimalla monimutkaisen logiikan kustomoituihin koukkuihin voit yksinkertaistaa komponenttejasi, vähentää koodin päällekkäisyyttä ja parantaa sovellustesi yleistä rakennetta. Ota kustomoidut koukut käyttöön ja vapauta niiden potentiaali rakentaaksesi vankempia ja skaalautuvampia React-sovelluksia.
Aloita tunnistamalla koodikannastasi alueita, joissa logiikka toistuu useissa komponenteissa. Refaktoroi sitten se logiikka kustomoiduiksi koukuiksi. Ajan myötä rakennat kirjaston uudelleenkäytettäviä koukkuja, jotka nopeuttavat kehitysprosessiasi ja parantavat koodisi laatua.
Muista noudattaa parhaita käytäntöjä, välttää yleisiä sudenkuoppia ja tutkia edistyneitä malleja saadaksesi kaiken irti kustomoiduista koukuista. Harjoittelun ja kokemuksen myötä sinusta tulee kustomoitujen koukkujen mestari ja tehokkaampi React-kehittäjä.