Frontend Academy · leksjon

Egendefinerte hooks: hente ut gjenbrukbar logikk

Flytt statefull logikk til egendefinerte use*-funksjoner for å dele atferd mellom komponenter uten å duplisere kode eller løfte state.

Leksjon 4 av 413 trinn

Egendefinerte hooks: hente ut gjenbrukbar logikk er en gratis leksjon i Frontend Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Frontend Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Frontend Academy inneholder totalt 4 leksjoner.

Hva er egendefinerte hooker

En egendefinert hook er en JavaScript-funksjon med et navn som begynner med use, og som internt kaller andre hooker. Egendefinerte hooker lar deg trekke ut tilstandslogikk slik at flere komponenter kan dele den uten å kopiere og lime inn kode.

Trekke ut logikk til en egendefinert hook

Finn logikk som er duplisert på tvers av komponenter (henting av data, lasting og feil, vindusstørrelse eller lokal lagring), og flytt den inn i en egendefinert hook.

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handler = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handler);
    return () => window.removeEventListener('resize', handler);
  }, []);

  return width;
}

// Usage:
const width = useWindowWidth();
const isMobile = width < 768;

useFetch — hook for datainnhenting

En gjenbrukbar hook for datainnhenting som alle komponenter kan bruke til å laste inn data fra en URL.

function useFetch<T>(url: string) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const controller = new AbortController();
    async function load() {
      try {
        const res = await fetch(url, { signal: controller.signal });
        if (!res.ok) throw new Error(`${res.status}`);
        setData(await res.json());
      } catch (err) {
        if ((err as DOMException).name !== 'AbortError')
          setError((err as Error).message);
      } finally { setLoading(false); }
    }
    load();
    return () => controller.abort();
  }, [url]);

  return { data, loading, error };
}

useLocalStorage-hook

En egendefinert hook som synkroniserer en verdi med localStorage og holder den synkronisert på tvers av faner via storage-hendelsen.

function useLocalStorage<T>(key: string, initialValue: T) {
  const [value, setValue] = useState<T>(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initialValue;
  });

  const set = useCallback((newValue: T) => {
    setValue(newValue);
    localStorage.setItem(key, JSON.stringify(newValue));
  }, [key]);

  return [value, set] as const;
}

Egendefinerte hooker deler logikk, ikke tilstand

Hver komponent som kaller en egendefinert hook, får sin egen uavhengige tilstand. Hooker er ikke singletons — de er funksjonskall som oppretter isolerte tilstandsinstanser.

Navnekonvensjoner

Navn på egendefinerte hooker må begynne med use. Dette håndheves av ESLints lintregler for react-hooks, som sørger for at hooker kalles på toppnivå og i riktig rekkefølge.

Returnere flere verdier

Egendefinerte hooker returnerer vanligvis et objekt (navngitte verdier) eller en tuppel (som useState). Tupler lar deg bruke destrukturering med egendefinerte navn, mens objekter forklarer seg selv.

// Tuple (like useState):
const [value, setValue] = useLocalStorage('key', 0);

// Object (more descriptive):
const { data, loading, error, refetch } = useFetch('/api/users');

useDebounce-hook

Debounce en verdi: oppdater den først etter at brukeren har sluttet å skrive i et angitt tidsrom.

function useDebounce<T>(value: T, delay: number): T {
  const [debounced, setDebounced] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debounced;
}

// Usage:
const debouncedSearch = useDebounce(searchTerm, 300);
useEffect(() => { search(debouncedSearch); }, [debouncedSearch]);

useMediaQuery-hook

Pakker window.matchMedia inn i en hook for reaktiv lesing av resultater fra CSS-mediespørringer.

function useMediaQuery(query: string): boolean {
  const [matches, setMatches] = useState(() => window.matchMedia(query).matches);

  useEffect(() => {
    const mq = window.matchMedia(query);
    const handler = (e: MediaQueryListEvent) => setMatches(e.matches);
    mq.addEventListener('change', handler);
    return () => mq.removeEventListener('change', handler);
  }, [query]);

  return matches;
}

Teste egendefinerte hooker

Bruk verktøyet renderHook() fra @testing-library/react til å teste egendefinerte hooker isolert, uten å pakke dem inn i en komponent.

import { renderHook, act } from '@testing-library/react';

test('useCounter increments', () => {
  const { result } = renderHook(() => useCounter(0));
  expect(result.current.count).toBe(0);
  act(() => result.current.increment());
  expect(result.current.count).toBe(1);
});

Publiserte hook-biblioteker

Fellesskapsbiblioteker for hooker tilbyr hundrevis av testede hooker: @uidotdev/usehooks, react-use, usehooks-ts. Før du skriver en egendefinert hook, bør du sjekke om det allerede finnes en godt testet versjon.

Hurtigsjekk

Hva skjer med tilstanden inne i en egendefinert hook når den kalles av to forskjellige komponenter?

Oppsummering: egendefinerte hooker

Egendefinerte hooker trekker ut tilstandslogikk for gjenbruk. Navnet skal ha prefikset use. Hver komponent som kaller hooken, får en uavhengig tilstand. Returner objekter eller tupler. Vanlige mønstre er useFetch, useLocalStorage, useDebounce og useMediaQuery. Test med renderHook(). Sjekk fellesskapsbiblioteker før du skriver alt fra grunnen av.

Gratis å komme i gang

Lær deg HTML med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
41
Leksjoner
163

Ofte stilte spørsmål

Er leksjonen «Egendefinerte hooks: hente ut gjenbrukbar logikk» gratis?

Ja – hele teksten i «Egendefinerte hooks: hente ut gjenbrukbar logikk» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Frontend Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Frontend Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Egendefinerte hooks: hente ut gjenbrukbar logikk»?

Flytt statefull logikk til egendefinerte use*-funksjoner for å dele atferd mellom komponenter uten å duplisere kode eller løfte state. Du øver på Frontend Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Frontend Academy?

Ingen tidligere erfaring er nødvendig. Frontend Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «Egendefinerte hooks: hente ut gjenbrukbar logikk»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Frontend Academy-leksjonen?

Ja. Alle Frontend Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. useContext for global state
  2. useReducer for kompleks state
  3. useMemo og useCallback for ytelse
  4. Egendefinerte hooks: hente ut gjenbrukbar logikk
← Tilbake til Frontend Academy