Norsk

Frigjør kraften i gjenbrukbar logikk i React-applikasjonene dine med egendefinerte hooks. Lær hvordan du lager og utnytter egendefinerte hooks for renere og mer vedlikeholdbar kode.

Egendefinerte Hooks: Gjenbrukbare logikkmønstre i React

React Hooks revolusjonerte måten vi skriver React-komponenter på ved å introdusere tilstand- og livssyklusfunksjoner til funksjonelle komponenter. Blant de mange fordelene de tilbyr, skiller egendefinerte hooks seg ut som en kraftig mekanisme for å trekke ut og gjenbruke logikk på tvers av flere komponenter. Dette blogginnlegget vil dykke dypt inn i verdenen av egendefinerte hooks, og utforske deres fordeler, hvordan de lages og brukes med praktiske eksempler.

Hva er egendefinerte Hooks?

I bunn og grunn er en egendefinert hook en JavaScript-funksjon som starter med ordet "use" og kan kalle andre hooks. De lar deg trekke ut komponentlogikk i gjenbrukbare funksjoner. Dette er en kraftig måte å dele tilstandsbasert logikk, bivirkninger eller annen kompleks atferd mellom komponenter uten å ty til render props, higher-order components eller andre komplekse mønstre.

Nøkkelegenskaper for egendefinerte Hooks:

Fordeler med å bruke egendefinerte Hooks

Egendefinerte hooks tilbyr flere betydelige fordeler i React-utvikling:

Å lage din første egendefinerte Hook

La oss illustrere hvordan man lager en egendefinert hook med et praktisk eksempel: en hook som sporer vindusstørrelsen.

Eksempel: useWindowSize

Denne hooken vil returnere den nåværende bredden og høyden på nettleservinduet. Den vil også oppdatere disse verdiene når vinduet endrer størrelse.

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

    // Fjern hendelseslytter ved opprydding
    return () => window.removeEventListener('resize', handleResize);
  }, []); // Tomt array sikrer at effekten kun kjøres ved montering

  return windowSize;
}

export default useWindowSize;

Forklaring:

  1. Importer nødvendige Hooks: Vi importerer useState og useEffect fra React.
  2. Definer hooken: Vi lager en funksjon kalt useWindowSize, som følger navnekonvensjonen.
  3. Initialiser tilstand: Vi bruker useState for å initialisere windowSize-tilstanden med den opprinnelige bredden og høyden på vinduet.
  4. Sett opp hendelseslytter: Vi bruker useEffect for å legge til en 'resize'-hendelseslytter på vinduet. Når vinduet endrer størrelse, oppdaterer handleResize-funksjonen windowSize-tilstanden.
  5. Opprydding: Vi returnerer en oppryddingsfunksjon fra useEffect for å fjerne hendelseslytteren når komponenten avmonteres. Dette forhindrer minnelekkasjer.
  6. Returner verdier: Hooken returnerer windowSize-objektet, som inneholder den nåværende bredden og høyden på vinduet.

Å bruke den egendefinerte Hooken i en komponent

Nå som vi har laget vår egendefinerte hook, la oss se hvordan vi kan bruke den i en React-komponent.

import React from 'react';
import useWindowSize from './useWindowSize';

function MyComponent() {
  const { width, height } = useWindowSize();

  return (
    

Vindusbredde: {width}px

Vindushøyde: {height}px

); } export default MyComponent;

Forklaring:

  1. Importer hooken: Vi importerer den egendefinerte hooken useWindowSize.
  2. Kall på hooken: Vi kaller på useWindowSize-hooken inne i komponenten.
  3. Få tilgang til verdier: Vi destrukturerer det returnerte objektet for å hente width- og height-verdiene.
  4. Render verdier: Vi rendrer bredde- og høydeverdiene i komponentens brukergrensesnitt.

Enhver komponent som bruker useWindowSize vil automatisk oppdateres når vindusstørrelsen endres.

Mer komplekse eksempler

La oss utforske noen mer avanserte bruksområder for egendefinerte hooks.

Eksempel: useLocalStorage

Denne hooken lar deg enkelt lagre og hente data fra local storage.

import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {
  // Tilstand for å lagre verdien vår
  // Send startverdi til useState slik at logikken kun kjøres én gang
  const [storedValue, setStoredValue] = useState(() => {
    try {
      // Hent fra local storage med nøkkel
      const item = window.localStorage.getItem(key);
      // Pars lagret json eller returner startverdi hvis ingen finnes
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      // Hvis feil, returner også startverdi
      console.log(error);
      return initialValue;
    }
  });

  // Returner en innpakket versjon av useState sin setter-funksjon som ...
  // ... lagrer den nye verdien til localStorage.
  const setValue = (value) => {
    try {
      // Tillat at verdien er en funksjon slik at vi har samme API som useState
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      // Lagre til local storage
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
      // Lagre tilstand
      setStoredValue(valueToStore);
    } catch (error) {
      // En mer avansert implementering ville håndtert feilsituasjonen
      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;

Bruk:

import React from 'react';
import useLocalStorage from './useLocalStorage';

function MyComponent() {
  const [name, setName] = useLocalStorage('name', 'Guest');

  return (
    

Hallo, {name}!

setName(e.target.value)} />
); } export default MyComponent;

Eksempel: useFetch

Denne hooken innkapsler logikken for å hente data fra et API.

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 error! 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;

Bruk:

import React from 'react';
import useFetch from './useFetch';

function MyComponent() {
  const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos/1');

  if (loading) return 

Laster...

; if (error) return

Feil: {error.message}

; return (

Tittel: {data.title}

Fullført: {data.completed ? 'Ja' : 'Nei'}

); } export default MyComponent;

Beste praksis for egendefinerte Hooks

For å sikre at dine egendefinerte hooks er effektive og vedlikeholdbare, følg disse beste praksisene:

Vanlige fallgruver å unngå

Avanserte mønstre

Komponering av egendefinerte Hooks

Egendefinerte hooks kan komponeres sammen for å skape mer kompleks logikk. For eksempel kan du kombinere en useLocalStorage-hook med en useFetch-hook for å automatisk lagre hentet data til local storage.

Dele logikk mellom Hooks

Hvis flere egendefinerte hooks deler felles logikk, kan du trekke ut den logikken i en separat hjelpefunksjon og gjenbruke den i begge hooks.

Bruke Context med egendefinerte Hooks

Egendefinerte hooks kan brukes sammen med React Context for å få tilgang til og oppdatere global tilstand. Dette lar deg lage gjenbrukbare komponenter som er bevisste på og kan interagere med applikasjonens globale tilstand.

Eksempler fra den virkelige verden

Her er noen eksempler på hvordan egendefinerte hooks kan brukes i virkelige applikasjoner:

Eksempel: useGeolocation-hook for flerkulturelle applikasjoner som karttjenester eller leveringstjenester

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: 'Geoposisjonering støttes ikke av denne nettleseren.',
      });
      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;

Konklusjon

Egendefinerte hooks er et kraftig verktøy for å skrive renere, mer gjenbrukbar og mer vedlikeholdbar React-kode. Ved å innkapsle kompleks logikk i egendefinerte hooks kan du forenkle komponentene dine, redusere kodeduplisering og forbedre den overordnede strukturen i applikasjonene dine. Omfavn egendefinerte hooks og frigjør potensialet deres til å bygge mer robuste og skalerbare React-applikasjoner.

Start med å identifisere områder i din eksisterende kodebase der logikk gjentas på tvers av flere komponenter. Deretter, refaktorer den logikken til egendefinerte hooks. Over tid vil du bygge et bibliotek av gjenbrukbare hooks som vil akselerere utviklingsprosessen og forbedre kvaliteten på koden din.

Husk å følge beste praksis, unngå vanlige fallgruver og utforske avanserte mønstre for å få mest mulig ut av egendefinerte hooks. Med øvelse og erfaring vil du bli en mester i egendefinerte hooks og en mer effektiv React-utvikler.