Polski

Odkryj moc logiki wielokrotnego użytku w aplikacjach React dzięki własnym hookom. Naucz się, jak je tworzyć, aby kod był czystszy i łatwiejszy w utrzymaniu.

Własne Hooki: Wzorce Logiki Wielokrotnego Użytku w React

Hooki React zrewolucjonizowały sposób, w jaki piszemy komponenty w React, wprowadzając stan i funkcje cyklu życia do komponentów funkcyjnych. Wśród wielu korzyści, jakie oferują, własne hooki wyróżniają się jako potężny mechanizm do ekstrakcji i ponownego wykorzystywania logiki w wielu komponentach. Ten wpis na blogu zagłębi się w świat własnych hooków, badając ich korzyści, tworzenie i użycie na praktycznych przykładach.

Czym są Własne Hooki?

W skrócie, własny hook to funkcja JavaScript, która zaczyna się od słowa „use” i może wywoływać inne hooki. Pozwalają one na wydzielenie logiki komponentu do funkcji wielokrotnego użytku. Jest to potężny sposób na współdzielenie logiki stanowej, efektów ubocznych lub innych złożonych zachowań między komponentami bez uciekania się do render props, komponentów wyższego rzędu (HOC) czy innych skomplikowanych wzorców.

Kluczowe cechy Własnych Hooków:

Zalety Używania Własnych Hooków

Własne hooki oferują kilka znaczących zalet w programowaniu w React:

Tworzenie Pierwszego Własnego Hooka

Zilustrujmy tworzenie własnego hooka na praktycznym przykładzie: hooka, który śledzi rozmiar okna.

Przykład: useWindowSize

Ten hook zwróci aktualną szerokość i wysokość okna przeglądarki. Będzie również aktualizował te wartości, gdy okno zostanie zmienione.

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

    // Remove event listener on cleanup
    return () => window.removeEventListener('resize', handleResize);
  }, []); // Empty array ensures that effect is only run on mount

  return windowSize;
}

export default useWindowSize;

Wyjaśnienie:

  1. Import niezbędnych hooków: Importujemy useState i useEffect z Reacta.
  2. Definiowanie hooka: Tworzymy funkcję o nazwie useWindowSize, zgodnie z konwencją nazewnictwa.
  3. Inicjalizacja stanu: Używamy useState do zainicjowania stanu windowSize początkową szerokością i wysokością okna.
  4. Konfiguracja nasłuchiwania zdarzeń: Używamy useEffect, aby dodać nasłuchiwacz zdarzenia „resize” do obiektu window. Kiedy okno jest zmieniane, funkcja handleResize aktualizuje stan windowSize.
  5. Czyszczenie: Zwracamy funkcję czyszczącą z useEffect, aby usunąć nasłuchiwacz zdarzeń, gdy komponent zostanie odmontowany. Zapobiega to wyciekom pamięci.
  6. Zwracane wartości: Hook zwraca obiekt windowSize, zawierający aktualną szerokość i wysokość okna.

Używanie Własnego Hooka w Komponencie

Teraz, gdy stworzyliśmy nasz własny hook, zobaczmy, jak go używać w komponencie React.

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

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

  return (
    

Window width: {width}px

Window height: {height}px

); } export default MyComponent;

Wyjaśnienie:

  1. Import hooka: Importujemy własny hook useWindowSize.
  2. Wywołanie hooka: Wywołujemy hook useWindowSize wewnątrz komponentu.
  3. Dostęp do wartości: Destrukturyzujemy zwrócony obiekt, aby uzyskać wartości width i height.
  4. Renderowanie wartości: Renderujemy wartości szerokości i wysokości w interfejsie użytkownika komponentu.

Każdy komponent, który używa useWindowSize, będzie automatycznie aktualizowany, gdy zmieni się rozmiar okna.

Bardziej Złożone Przykłady

Przyjrzyjmy się kilku bardziej zaawansowanym przypadkom użycia własnych hooków.

Przykład: useLocalStorage

Ten hook pozwala na łatwe przechowywanie i pobieranie danych z local storage.

import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {
  // State to store our value
  // Pass initial value to useState so logic is only executed once
  const [storedValue, setStoredValue] = useState(() => {
    try {
      // Get from local storage by key
      const item = window.localStorage.getItem(key);
      // Parse stored json or if none return initialValue
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      // If error also return initialValue
      console.log(error);
      return initialValue;
    }
  });

  // Return a wrapped version of useState's setter function that ...
  // ... persists the new value to localStorage.
  const setValue = (value) => {
    try {
      // Allow value to be a function so we have same API as useState
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      // Save to local storage
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
      // Save state
      setStoredValue(valueToStore);
    } catch (error) {
      // A more advanced implementation would handle the error case
      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;

Użycie:

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

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

  return (
    

Hello, {name}!

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

Przykład: useFetch

Ten hook hermetyzuje logikę pobierania danych z 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;

Użycie:

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

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

  if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; return (

Title: {data.title}

Completed: {data.completed ? 'Yes' : 'No'}

); } export default MyComponent;

Dobre Praktyki dla Własnych Hooków

Aby zapewnić, że Twoje własne hooki są skuteczne i łatwe w utrzymaniu, postępuj zgodnie z poniższymi dobrymi praktykami:

Częste Pułapki, Których Należy Unikać

Zaawansowane Wzorce

Komponowanie Własnych Hooków

Własne hooki można komponować razem, aby tworzyć bardziej złożoną logikę. Na przykład, można połączyć hook useLocalStorage z hookiem useFetch, aby automatycznie zapisywać pobrane dane w local storage.

Dzielenie Logiki Między Hookami

Jeśli wiele własnych hooków dzieli wspólną logikę, można tę logikę wydzielić do osobnej funkcji pomocniczej i ponownie jej użyć w obu hookach.

Używanie Kontekstu z Własnymi Hookami

Własne hooki można używać w połączeniu z React Context, aby uzyskać dostęp i aktualizować globalny stan. Pozwala to na tworzenie komponentów wielokrotnego użytku, które są świadome globalnego stanu aplikacji i mogą z nim wchodzić w interakcje.

Przykłady z Prawdziwego Świata

Oto kilka przykładów, jak własne hooki mogą być używane w rzeczywistych aplikacjach:

Przykład: hook useGeolocation dla aplikacji międzykulturowych, takich jak mapy czy usługi dostawcze

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: 'Geolocation is not supported by this browser.',
      });
      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;

Podsumowanie

Własne hooki to potężne narzędzie do pisania czystszego, bardziej reużywalnego i łatwiejszego w utrzymaniu kodu React. Poprzez hermetyzację złożonej logiki we własnych hookach, możesz uprościć swoje komponenty, zredukować duplikację kodu i poprawić ogólną strukturę swoich aplikacji. Wykorzystaj własne hooki i odblokuj ich potencjał do budowania bardziej solidnych i skalowalnych aplikacji React.

Zacznij od zidentyfikowania w swojej istniejącej bazie kodu obszarów, w których logika jest powtarzana w wielu komponentach. Następnie zrefaktoryzuj tę logikę do własnych hooków. Z czasem zbudujesz bibliotekę hooków wielokrotnego użytku, która przyspieszy proces rozwoju i poprawi jakość Twojego kodu.

Pamiętaj, aby postępować zgodnie z najlepszymi praktykami, unikać typowych pułapek i odkrywać zaawansowane wzorce, aby w pełni wykorzystać możliwości własnych hooków. Dzięki praktyce i doświadczeniu staniesz się mistrzem własnych hooków i bardziej skutecznym programistą React.

Własne Hooki: Wzorce Logiki Wielokrotnego Użytku w React | MLOG