Français

Libérez la puissance de la logique réutilisable dans vos applications React avec les hooks personnalisés. Apprenez à créer et utiliser des hooks personnalisés pour un code plus propre et plus facile à maintenir.

Hooks Personnalisés : Patrons de Logique Réutilisable dans React

Les hooks de React ont révolutionné la façon dont nous écrivons les composants React en introduisant l'état et les fonctionnalités de cycle de vie aux composants fonctionnels. Parmi les nombreux avantages qu'ils offrent, les hooks personnalisés se distinguent comme un mécanisme puissant pour extraire et réutiliser la logique entre plusieurs composants. Cet article de blog explorera en profondeur le monde des hooks personnalisés, en examinant leurs avantages, leur création et leur utilisation avec des exemples pratiques.

Que sont les Hooks Personnalisés ?

Essentiellement, un hook personnalisé est une fonction JavaScript qui commence par le mot « use » et peut appeler d'autres hooks. Ils vous permettent d'extraire la logique d'un composant dans des fonctions réutilisables. C'est un moyen puissant de partager une logique avec état (stateful), des effets de bord ou d'autres comportements complexes entre les composants sans recourir aux render props, aux composants d'ordre supérieur (HOC) ou à d'autres patrons complexes.

Caractéristiques Clés des Hooks Personnalisés :

Avantages de l'Utilisation des Hooks Personnalisés

Les hooks personnalisés offrent plusieurs avantages significatifs dans le développement React :

Créer Votre Premier Hook Personnalisé

Illustrons la création d'un hook personnalisé avec un exemple pratique : un hook qui suit la taille de la fenêtre.

Exemple : useWindowSize

Ce hook retournera la largeur et la hauteur actuelles de la fenêtre du navigateur. Il mettra également à jour ces valeurs lorsque la fenêtre sera redimensionnée.

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

    // Supprimer l'écouteur d'événement au nettoyage
    return () => window.removeEventListener('resize', handleResize);
  }, []); // Le tableau vide assure que l'effet ne s'exécute qu'au montage

  return windowSize;
}

export default useWindowSize;

Explication :

  1. Importer les Hooks Nécessaires : Nous importons useState et useEffect de React.
  2. Définir le Hook : Nous créons une fonction nommée useWindowSize, en respectant la convention de nommage.
  3. Initialiser l'État : Nous utilisons useState pour initialiser l'état windowSize avec la largeur et la hauteur initiales de la fenêtre.
  4. Mettre en Place un Écouteur d'Événement : Nous utilisons useEffect pour ajouter un écouteur d'événement de redimensionnement à la fenêtre. Lorsque la fenêtre est redimensionnée, la fonction handleResize met à jour l'état windowSize.
  5. Nettoyage : Nous retournons une fonction de nettoyage depuis useEffect pour supprimer l'écouteur d'événement lorsque le composant est démonté. Cela prévient les fuites de mémoire.
  6. Retourner les Valeurs : Le hook retourne l'objet windowSize, contenant la largeur et la hauteur actuelles de la fenêtre.

Utiliser le Hook Personnalisé dans un Composant

Maintenant que nous avons créé notre hook personnalisé, voyons comment l'utiliser dans un composant React.

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

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

  return (
    

Largeur de la fenêtre : {width}px

Hauteur de la fenêtre : {height}px

); } export default MyComponent;

Explication :

  1. Importer le Hook : Nous importons le hook personnalisé useWindowSize.
  2. Appeler le Hook : Nous appelons le hook useWindowSize à l'intérieur du composant.
  3. Accéder aux Valeurs : Nous déstructurons l'objet retourné pour obtenir les valeurs width et height.
  4. Afficher les Valeurs : Nous affichons les valeurs de largeur et de hauteur dans l'interface utilisateur du composant.

Tout composant utilisant useWindowSize se mettra automatiquement à jour lorsque la taille de la fenêtre changera.

Exemples Plus Complexes

Explorons quelques cas d'utilisation plus avancés pour les hooks personnalisés.

Exemple : useLocalStorage

Ce hook vous permet de stocker et de récupérer facilement des données du stockage local.

import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {
  // État pour stocker notre valeur
  // Passer la valeur initiale à useState pour que la logique ne soit exécutée qu'une fois
  const [storedValue, setStoredValue] = useState(() => {
    try {
      // Obtenir depuis le stockage local par clé
      const item = window.localStorage.getItem(key);
      // Analyser le JSON stocké ou retourner initialValue s'il n'y en a pas
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      // En cas d'erreur, retourner également initialValue
      console.log(error);
      return initialValue;
    }
  });

  // Retourner une version encapsulée de la fonction setter de useState qui...
  // ... persiste la nouvelle valeur dans localStorage.
  const setValue = (value) => {
    try {
      // Permettre à la valeur d'être une fonction pour avoir la même API que useState
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      // Sauvegarder dans le stockage local
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
      // Sauvegarder l'état
      setStoredValue(valueToStore);
    } catch (error) {
      // Une implémentation plus avancée gérerait le cas d'erreur
      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;

Utilisation :

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

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

  return (
    

Bonjour, {name} !

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

Exemple : useFetch

Ce hook encapsule la logique de récupération de données depuis une 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(`Erreur HTTP ! statut : ${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;

Utilisation :

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

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

  if (loading) return 

Chargement...

; if (error) return

Erreur : {error.message}

; return (

Titre : {data.title}

Terminé : {data.completed ? 'Oui' : 'Non'}

); } export default MyComponent;

Meilleures Pratiques pour les Hooks Personnalisés

Pour garantir que vos hooks personnalisés sont efficaces et maintenables, suivez ces meilleures pratiques :

Pièges Courants à Éviter

Patrons Avancés

Composer des Hooks Personnalisés

Les hooks personnalisés peuvent être composés ensemble pour créer une logique plus complexe. Par exemple, vous pourriez combiner un hook useLocalStorage avec un hook useFetch pour persister automatiquement les données récupérées dans le stockage local.

Partager la Logique entre les Hooks

Si plusieurs hooks personnalisés partagent une logique commune, vous pouvez extraire cette logique dans une fonction utilitaire distincte et la réutiliser dans les deux hooks.

Utiliser le Contexte avec les Hooks Personnalisés

Les hooks personnalisés peuvent être utilisés en conjonction avec le Contexte de React pour accéder et mettre à jour l'état global. Cela vous permet de créer des composants réutilisables qui sont conscients de l'état global de l'application et peuvent interagir avec lui.

Exemples du Monde Réel

Voici quelques exemples de la façon dont les hooks personnalisés peuvent être utilisés dans des applications du monde réel :

Exemple : hook useGeolocation pour les applications interculturelles comme les services de cartographie ou de livraison

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 géolocalisation n\'est pas prise en charge par ce navigateur.',
      });
      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;

Conclusion

Les hooks personnalisés sont un outil puissant pour écrire du code React plus propre, plus réutilisable et plus maintenable. En encapsulant la logique complexe dans des hooks personnalisés, vous pouvez simplifier vos composants, réduire la duplication de code et améliorer la structure globale de vos applications. Adoptez les hooks personnalisés et libérez leur potentiel pour construire des applications React plus robustes et évolutives.

Commencez par identifier les zones de votre base de code existante où la logique est répétée entre plusieurs composants. Ensuite, refactorisez cette logique en hooks personnalisés. Au fil du temps, vous construirez une bibliothèque de hooks réutilisables qui accélérera votre processus de développement et améliorera la qualité de votre code.

N'oubliez pas de suivre les meilleures pratiques, d'éviter les pièges courants et d'explorer les patrons avancés pour tirer le meilleur parti des hooks personnalisés. Avec de la pratique et de l'expérience, vous deviendrez un maître des hooks personnalisés et un développeur React plus efficace.