Italiano

Sblocca il potere della logica riutilizzabile nelle tue applicazioni React con gli hook personalizzati. Impara a creare e sfruttare gli hook personalizzati per un codice più pulito e manutenibile.

Hook Personalizzati: Pattern di Logica Riutilizzabile in React

Gli Hook di React hanno rivoluzionato il modo in cui scriviamo i componenti React, introducendo lo stato e le funzionalità del ciclo di vita nei componenti funzionali. Tra i molti vantaggi che offrono, gli hook personalizzati si distinguono come un potente meccanismo per estrarre e riutilizzare la logica tra più componenti. Questo articolo del blog approfondirà il mondo degli hook personalizzati, esplorandone i vantaggi, la creazione e l'utilizzo con esempi pratici.

Cosa sono gli Hook Personalizzati?

In sostanza, un hook personalizzato è una funzione JavaScript che inizia con la parola "use" e può chiamare altri hook. Ti permettono di estrarre la logica del componente in funzioni riutilizzabili. Questo è un modo potente per condividere logica stateful, effetti collaterali o altri comportamenti complessi tra i componenti senza ricorrere a render props, higher-order components o altri pattern complessi.

Caratteristiche Chiave degli Hook Personalizzati:

Vantaggi dell'Utilizzo degli Hook Personalizzati

Gli hook personalizzati offrono diversi vantaggi significativi nello sviluppo con React:

Creare il Tuo Primo Hook Personalizzato

Illustriamo la creazione di un hook personalizzato con un esempio pratico: un hook che tiene traccia delle dimensioni della finestra.

Esempio: useWindowSize

Questo hook restituirà la larghezza e l'altezza attuali della finestra del browser. Aggiornerà anche questi valori quando la finestra viene ridimensionata.

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

    // Rimuovi l'event listener durante la pulizia
    return () => window.removeEventListener('resize', handleResize);
  }, []); // L'array vuoto assicura che l'effetto venga eseguito solo al mount

  return windowSize;
}

export default useWindowSize;

Spiegazione:

  1. Importare gli Hook Necessari: Importiamo useState e useEffect da React.
  2. Definire l'Hook: Creiamo una funzione chiamata useWindowSize, rispettando la convenzione di nomenclatura.
  3. Inizializzare lo Stato: Usiamo useState per inizializzare lo stato windowSize con la larghezza e l'altezza iniziali della finestra.
  4. Impostare l'Event Listener: Usiamo useEffect per aggiungere un event listener 'resize' alla finestra. Quando la finestra viene ridimensionata, la funzione handleResize aggiorna lo stato windowSize.
  5. Pulizia: Restituiamo una funzione di pulizia da useEffect per rimuovere l'event listener quando il componente viene smontato. Questo previene perdite di memoria.
  6. Restituire i Valori: L'hook restituisce l'oggetto windowSize, contenente la larghezza e l'altezza correnti della finestra.

Utilizzare l'Hook Personalizzato in un Componente

Ora che abbiamo creato il nostro hook personalizzato, vediamo come usarlo in un componente React.

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

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

  return (
    

Larghezza finestra: {width}px

Altezza finestra: {height}px

); } export default MyComponent;

Spiegazione:

  1. Importare l'Hook: Importiamo l'hook personalizzato useWindowSize.
  2. Chiamare l'Hook: Chiamiamo l'hook useWindowSize all'interno del componente.
  3. Accedere ai Valori: Destrutturiamo l'oggetto restituito per ottenere i valori width e height.
  4. Renderizzare i Valori: Renderizziamo i valori di larghezza e altezza nell'interfaccia utente del componente.

Qualsiasi componente che utilizza useWindowSize si aggiornerà automaticamente al variare delle dimensioni della finestra.

Esempi più Complessi

Esploriamo alcuni casi d'uso più avanzati per gli hook personalizzati.

Esempio: useLocalStorage

Questo hook permette di memorizzare e recuperare facilmente dati dal local storage.

import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {
  // Stato per memorizzare il nostro valore
  // Passa il valore iniziale a useState in modo che la logica venga eseguita una sola volta
  const [storedValue, setStoredValue] = useState(() => {
    try {
      // Ottieni dal local storage tramite chiave
      const item = window.localStorage.getItem(key);
      // Analizza il JSON memorizzato o, se non presente, restituisci initialValue
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      // In caso di errore, restituisci anche initialValue
      console.log(error);
      return initialValue;
    }
  });

  // Restituisce una versione "incapsulata" della funzione setter di useState che...
  // ...rende persistente il nuovo valore nel localStorage.
  const setValue = (value) => {
    try {
      // Permetti al valore di essere una funzione in modo da avere la stessa API di useState
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      // Salva nel local storage
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
      // Salva lo stato
      setStoredValue(valueToStore);
    } catch (error) {
      // Un'implementazione più avanzata gestirebbe il caso di errore
      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;

Utilizzo:

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

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

  return (
    

Ciao, {name}!

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

Esempio: useFetch

Questo hook incapsula la logica per il recupero dei dati da un'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(`Errore HTTP! 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;

Utilizzo:

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

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

  if (loading) return 

Caricamento...

; if (error) return

Errore: {error.message}

; return (

Titolo: {data.title}

Completato: {data.completed ? 'Sì' : 'No'}

); } export default MyComponent;

Best Practice per gli Hook Personalizzati

Per assicurarti che i tuoi hook personalizzati siano efficaci e manutenibili, segui queste best practice:

Errori Comuni da Evitare

Pattern Avanzati

Comporre Hook Personalizzati

Gli hook personalizzati possono essere composti insieme per creare una logica più complessa. Ad esempio, potresti combinare un hook useLocalStorage con un hook useFetch per salvare automaticamente i dati recuperati nel local storage.

Condividere la Logica tra Hook

Se più hook personalizzati condividono una logica comune, puoi estrarre quella logica in una funzione di utilità separata e riutilizzarla in entrambi gli hook.

Usare il Contesto con gli Hook Personalizzati

Gli hook personalizzati possono essere utilizzati in combinazione con il Contesto di React per accedere e aggiornare lo stato globale. Questo ti permette di creare componenti riutilizzabili che sono consapevoli dello stato globale dell'applicazione e possono interagire con esso.

Esempi dal Mondo Reale

Ecco alcuni esempi di come gli hook personalizzati possono essere utilizzati in applicazioni reali:

Esempio: hook useGeolocation per applicazioni cross-culturali come servizi di mappatura o consegna

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: 'La geolocalizzazione non è supportata da questo 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;

Conclusione

Gli hook personalizzati sono uno strumento potente per scrivere codice React più pulito, riutilizzabile e manutenibile. Incapsulando la logica complessa negli hook personalizzati, puoi semplificare i tuoi componenti, ridurre la duplicazione del codice e migliorare la struttura generale delle tue applicazioni. Abbraccia gli hook personalizzati e sblocca il loro potenziale per costruire applicazioni React più robuste e scalabili.

Inizia identificando le aree nel tuo codice esistente in cui la logica viene ripetuta tra più componenti. Quindi, rifattorizza quella logica in hook personalizzati. Col tempo, costruirai una libreria di hook riutilizzabili che accelererà il tuo processo di sviluppo e migliorerà la qualità del tuo codice.

Ricorda di seguire le best practice, evitare gli errori comuni ed esplorare i pattern avanzati per ottenere il massimo dagli hook personalizzati. Con la pratica e l'esperienza, diventerai un maestro degli hook personalizzati e uno sviluppatore React più efficace.