Frontend Academy · Lektion

Egna hooks: extrahera återanvändbar logik

Flytta statefull logik till egna use*-funktioner för att dela beteende mellan komponenter utan att duplicera kod eller lyfta state.

Lektion 4 av 413 steg

Egna hooks: extrahera återanvändbar logik är en gratis lektion i Frontend Academy på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Frontend Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Frontend Academy innehåller totalt 4 lektioner.

Vad är anpassade hooks?

En anpassad hook är en JavaScript-funktion vars namn börjar med use och som internt anropar andra hooks. Med anpassade hooks kan ni extrahera tillståndslogik så att flera komponenter kan dela den utan att kopiera och klistra in kod.

Extrahera logik till en anpassad hook

Identifiera logik som dupliceras mellan komponenter (hämtning + laddning + felhantering, fönsterstorlek eller local storage) och flytta den till en anpassad 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 för datahämtning

En återanvändbar hook för datahämtning som alla komponenter kan använda för att läsa in data från 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 };
}

Hooken useLocalStorage

En anpassad hook som synkroniserar ett värde med localStorage och håller det synkroniserat mellan flikar via storage-händelsen.

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;
}

Anpassade hooks delar logik, inte tillstånd

Varje komponent som anropar en anpassad hook får sitt eget oberoende tillstånd. Hooks är inte singletoner — de är funktionsanrop som skapar isolerade tillståndsinstanser.

Namngivningskonventioner

Namn på anpassade hooks måste börja med use. Detta kontrolleras av ESLints lintregler för react-hooks, som säkerställer att hooks anropas på toppnivå och i rätt ordning.

Returnera flera värden

Anpassade hooks returnerar vanligtvis ett objekt (namngivna värden) eller en tupel (som useState). Tupler gör det möjligt att destrukturera med egna namn, medan objekt beskriver sig själva.

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

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

Hooken useDebounce

Debounca ett värde: uppdatera det först när användaren har slutat skriva under en angiven fördröjning.

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]);

Hooken useMediaQuery

Omsluter window.matchMedia i en hook för att reaktivt läsa resultatet av CSS-mediefrågor.

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;
}

Testa anpassade hooks

Använd verktyget renderHook() i @testing-library/react för att testa anpassade hooks isolerat utan att omsluta dem 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);
});

Publicerade hook-bibliotek

Community-bibliotek med hooks tillhandahåller hundratals testade hooks: @uidotdev/usehooks, react-use och usehooks-ts. Innan ni skriver en anpassad hook bör ni kontrollera om det redan finns en vältestad version.

Snabb kontroll

Vad händer med tillståndet inuti en anpassad hook när den anropas av två olika komponenter?

Sammanfattning: anpassade hooks

Anpassade hooks extraherar tillståndslogik för återanvändning. Namnge dem med prefixet use. Varje komponent som anropar hooken får ett oberoende tillstånd. Returnera objekt eller tupler. Vanliga mönster är useFetch, useLocalStorage, useDebounce och useMediaQuery. Testa med renderHook(). Kontrollera community-bibliotek innan ni skriver från grunden.

Gratis att börja

Lär dig HTML med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
41
Lektioner
163

Vanliga frågor

Är lektionen ”Egna hooks: extrahera återanvändbar logik” gratis?

Ja – hela texten till ”Egna hooks: extrahera återanvändbar logik” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Frontend Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Frontend Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Egna hooks: extrahera återanvändbar logik”?

Flytta statefull logik till egna use*-funktioner för att dela beteende mellan komponenter utan att duplicera kod eller lyfta state. Ni övar på Frontend Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Frontend Academy?

Du behöver inga förkunskaper. Utbildningen i Frontend Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Egna hooks: extrahera återanvändbar logik”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Frontend Academy-lektionen?

Ja. Varje Frontend Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. useContext för global state
  2. useReducer för komplex state
  3. useMemo och useCallback för prestanda
  4. Egna hooks: extrahera återanvändbar logik
← Tillbaka till Frontend Academy