OUJOOD.COM
Introduction
Les Custom Hooks sont des fonctions personnalisées qui permettent de réutiliser des fonctionnalités et de l'état entre plusieurs composants React. Ils offrent une solution élégante pour factoriser du code et éviter les duplications. Grâce aux Custom Hooks, vous pouvez encapsuler des logiques complexes dans des fonctions réutilisables, rendant ainsi votre code plus maintenable et scalable.
Dans ce chapitre, nous allons explorer :
- Qu'est-ce qu'un Custom Hook ?
- Comment créer un Custom Hook.
- Des exemples pratiques pour illustrer leur utilisation.
1. Qu'est-ce qu'un Custom Hook ?
Un Custom Hook est simplement une fonction JavaScript dont le nom commence par use
. Il peut appeler d'autres Hooks comme useState
, useEffect
, ou encore useReducer
. Voici pourquoi ils sont utiles :
- Réutilisation : Encapsulez des fonctionnalités communes dans un Custom Hook pour les réutiliser dans différents composants.
- Maintenabilité : Concentrez toute la logique d'un aspect spécifique (par exemple, la gestion d'un compteur) dans un seul endroit.
- Scalabilité : Simplifiez la gestion de l'état et des effets secondaires dans vos applications React.
2. Création d'un Custom Hook Simple
Voici un exemple simple où nous créons un Custom Hook appelé useCompteur
pour gérer un compteur réutilisable :
// useCompteur.js import { useState, useEffect } from 'react'; function useCompteur(initialValue = 0) { const [compte, setCompte] = useState(initialValue); // Effet secondaire : Affiche le compteur dans la console à chaque changement useEffect(() => { console.log(`Le compteur a changé : ${compte}`); }, [compte]); return [compte, setCompte]; } export default useCompteur;
Explication détaillée ligne par ligne :
-
import { useState, useEffect } from 'react';
:- Nous importons les Hooks
useState
etuseEffect
depuis React. useState
est utilisé pour gérer l'état local du compteur (compte
).useEffect
exécute un effet secondaire lorsqu'une certaine variable change.
- Nous importons les Hooks
-
function useCompteur(initialValue = 0) { ... }
:- Cette fonction définit notre Custom Hook appelé
useCompteur
. - Elle accepte un paramètre optionnel
initialValue
, qui spécifie la valeur initiale du compteur (par défaut :0
).
- Cette fonction définit notre Custom Hook appelé
-
const [compte, setCompte] = useState(initialValue);
:- Cette ligne initialise l'état local du compteur avec la valeur
initialValue
. setCompte
est une fonction permettant de mettre à jour cet état.
- Cette ligne initialise l'état local du compteur avec la valeur
-
useEffect(() => { ... }, [compte]);
:- Cet effet secondaire s'exécute à chaque fois que la valeur de
compte
change. console.log(`Le compteur a changé : ${compte}`);
: Affiche un message dans la console avec la nouvelle valeur du compteur.
- Cet effet secondaire s'exécute à chaque fois que la valeur de
-
return [compte, setCompte];
:- Notre Custom Hook retourne un tableau contenant la valeur actuelle du compteur (
compte
) et la fonction pour le mettre à jour (setCompte
).
- Notre Custom Hook retourne un tableau contenant la valeur actuelle du compteur (
-
export default useCompteur;
:- Cette ligne exporte notre Custom Hook pour qu'il soit utilisable dans d'autres fichiers ou composants.
3. Utilisation du Custom Hook dans un Composant
Maintenant que nous avons créé notre Custom Hook appelé useTheme
, voyons comment l'utiliser dans un composant React pour gérer dynamiquement le thème de notre application. Cet exemple illustrera clairement comment intégrer un Custom Hook dans un composant fonctionnel.
import React from 'react'; import useTheme from './useTheme'; // Importation du Custom Hook import { createRoot } from 'react-dom/client'; function App() { const [theme, toggleTheme] = useTheme(); // Utilisation du Custom Hook // Styles conditionnels basés sur le thème actuel const styles = { container: { padding: '20px', textAlign: 'center', fontFamily: 'Arial, sans-serif', backgroundColor: theme === 'dark' ? '#333' : '#f9f9f9', // Arrière-plan selon le thème color: theme === 'dark' ? 'white' : 'black' // Couleur du texte selon le thème }, button: { padding: '10px 20px', margin: '10px auto', display: 'block', border: 'none', borderRadius: '5px', cursor: 'pointer', backgroundColor: theme === 'dark' ? '#FFC107' : '#007BFF', // Couleur du bouton selon le thème color: 'white' } }; return ( <div style={styles.container}> <h1 style={{ color: theme === 'dark' ? '#FFC107' : '#007BFF' }}>Système de Thème avec Custom Hook</h1> <button onClick={toggleTheme} style={styles.button} > Changer de thème </button> <p>Thème actuel : {theme}</p> </div> ); } const root = createRoot(document.getElementById('root')); // Création de la racine React (React 18+) root.render(<App />); // Rendu du composant principal
Explication détaillée ligne par ligne :
-
import React from 'react';
:- Nous importons React pour utiliser ses fonctionnalités, notamment JSX.
-
import useTheme from './useTheme';
:- Cette ligne importe notre Custom Hook
useTheme
depuis le fichieruseTheme.js
. - Le Custom Hook encapsule toute la logique liée à la gestion du thème (initialisation, basculement, persistance).
- Cette ligne importe notre Custom Hook
-
import { createRoot } from 'react-dom/client';
:- Cette ligne importe la méthode
createRoot
depuisreact-dom/client
, recommandée pour React 18 et versions ultérieures. createRoot
remplaceReactDOM.render()
pour un rendu plus moderne et aligné avec les futures évolutions de React.
- Cette ligne importe la méthode
-
function App() { ... }
:- Ce composant fonctionnel est le point d'entrée de notre application.
- Il utilise notre Custom Hook
useTheme
pour gérer dynamiquement le thème global.
-
const [theme, toggleTheme] = useTheme();
:- Ici, nous utilisons notre Custom Hook
useTheme
pour initialiser deux valeurs :theme
(le thème actuel) ettoggleTheme
(la fonction pour basculer entre les thèmes). theme
représente soit'light'
(mode clair), soit'dark'
(mode sombre).toggleTheme
est une fonction qui alterne entre ces deux modes.
- Ici, nous utilisons notre Custom Hook
-
const styles = { ... };
:- Cette variable définit des styles CSS sous forme d'objets JavaScript pour personnaliser l'apparence de notre composant.
- container : Définit les styles du conteneur principal.
- backgroundColor : Change dynamiquement l'arrière-plan selon la valeur de
theme
. Sitheme
est'dark'
, l'arrière-plan devient noir (#333
); sinon, il reste blanc (#f9f9f9
). - color : Change dynamiquement la couleur du texte selon la valeur de
theme
. Sitheme
est'dark'
, le texte devient blanc; sinon, il reste noir. - button : Définit les styles du bouton "Changer de thème".
- backgroundColor : Change la couleur du fond du bouton selon la valeur de
theme
. En mode sombre, le bouton est orange (#FFC107
); en mode clair, il est bleu (#007BFF
). - color : Le texte du bouton reste toujours blanc (
white
) pour contraster avec les arrière-plans colorés.
-
<div style={styles.container}>
:- Cet élément
<div>
est stylisé avec les propriétés définies dansstyles.container
. - Son apparence change dynamiquement en fonction de la valeur actuelle de
theme
.
- Cet élément
-
<h1 style={{ color: theme === 'dark' ? '#FFC107' : '#007BFF' }}>...</h1>
:- Cet élément
<h1>
affiche un titre centré ("Système de Thème avec Custom Hook"). - La couleur du texte change dynamiquement selon la valeur de
theme
. En mode sombre, elle est orange (#FFC107
); en mode clair, elle est bleue (#007BFF
).
- Cet élément
-
<button onClick={toggleTheme} style={styles.button}>...</button>
:- Ce bouton permet à l'utilisateur de basculer entre les modes clair et sombre.
onClick={toggleTheme}
: Lorsque le bouton est cliqué, il appelle la fonctiontoggleTheme
renvoyée par notre Custom Hook.style={styles.button}
: Applique les styles définis dansstyles.button
, y compris la couleur de fond et du texte selon le thème actuel.
-
>p<Thème actuel : {theme}>/p<
:- Cet élément
<p>
affiche dynamiquement le thème actuel (theme
) : soit'light'
, soit'dark'
. - Grâce à cette indication visuelle, l'utilisateur peut voir immédiatement quel thème est activé.
- Cet élément
-
const root = createRoot(document.getElementById('root'));
:- Cette ligne crée une instance de racine React appelée
root
. document.getElementById('root')
spécifie l'élément HTML où notre application sera insérée.
- Cette ligne crée une instance de racine React appelée
-
root.render(<App />);
:- Cette ligne rend notre composant principal
App
dans l'élément HTML ayant l'idroot
. - En utilisant
createRoot
, nous garantissons une compatibilité avec React 18 et versions ultérieures.
- Cette ligne rend notre composant principal
Pourquoi Utiliser un Custom Hook dans ce Cas ?
En encapsulant toute la logique de gestion du thème dans un Custom Hook (useTheme
), nous obtenons plusieurs avantages significatifs :
- Réutilisation : La gestion du thème peut être partagée entre plusieurs composants sans duplication de code.
- Maintenabilité : Toute la logique liée au thème est centralisée dans un seul fichier (
useTheme.js
), facilitant ainsi les mises à jour ou modifications futures. - Scalabilité : Si nous souhaitons ajouter des fonctionnalités supplémentaires (par exemple, plusieurs thèmes ou animations), cela peut être fait facilement dans le Custom Hook sans affecter les composants qui l'utilisent.
- Optimisation des Performances : En évitant de recalculer inutilement des états ou effets secondaires dans chaque composant, nous réduisons la charge de travail de React.
Comment Fonctionne cet Exemple en Détail ?
Voici une explication pas à pas de ce qui se passe lorsqu'un utilisateur interagit avec notre application :
-
Initialisation du Thème : Lorsque le composant
App
est monté, il appelle notre Custom HookuseTheme
pour initialiser le thème actuel (theme
) et obtenir la fonctiontoggleTheme
. -
Affichage Dynamique : Les styles du composant (
styles.container
etstyles.button
) sont ajustés en fonction de la valeur actuelle detheme
. Par exemple, sitheme
est'dark'
, l'arrière-plan devient noir et le texte blanc. -
Basculement du Thème : Lorsque l'utilisateur clique sur le bouton "Changer de thème", la fonction
toggleTheme
est exécutée. Cela met à jour l'étattheme
viasetTheme
, tout en sauvegardant la nouvelle valeur dans lelocalStorage
pour une persistance entre les sessions. -
Re-render Automatique : Après que
theme
a été mis à jour, React détecte le changement d'état et re-rend le composantApp
avec les nouveaux styles adaptés au thème sélectionné.
4. Exemple Avancé : Gestion d'un Thème Global avec un Custom Hook
Imaginons que vous souhaitiez créer un système de thème global pour votre application React (par exemple, mode clair ou mode sombre). Au lieu de dupliquer cette logique dans plusieurs composants, nous pouvons encapsuler toute la gestion du thème dans un Custom Hook réutilisable.
// useTheme.js import { useState, useEffect } from 'react'; function useTheme(initialTheme = 'light') { const [theme, setTheme] = useState(initialTheme); // Enregistre le thème dans le localStorage pour une persistance entre les sessions useEffect(() => { const savedTheme = localStorage.getItem('theme'); if (savedTheme) { setTheme(savedTheme); // Charge le thème sauvegardé au montage } }, []); // Met à jour le thème et le stocke dans le localStorage const toggleTheme = () => { const newTheme = theme === 'light' ? 'dark' : 'light'; setTheme(newTheme); localStorage.setItem('theme', newTheme); // Persistance du thème }; return [theme, toggleTheme]; } export default useTheme; // App.js import React from 'react'; import useTheme from './useTheme'; import { createRoot } from 'react-dom/client'; function App() { const [theme, toggleTheme] = useTheme(); // Utilise le Custom Hook const styles = { container: { padding: '20px', textAlign: 'center', fontFamily: 'Arial, sans-serif' }, body: { backgroundColor: theme === 'dark' ? '#333' : '#f9f9f9', color: theme === 'dark' ? 'white' : 'black' } }; return ( <div style={styles.container}> <h1 style={{ color: theme === 'dark' ? '#FFC107' : '#007BFF' }}>Système de Thème avec Custom Hook</h1> <button onClick={toggleTheme} style={{ padding: '10px 20px', margin: '10px auto', display: 'block' }}> Changer de thème </button> <p>Thème actuel : {theme}</p> </div> ); } const root = createRoot(document.getElementById('root')); root.render(<App />);
Explication détaillée ligne par ligne :
-
function useTheme(initialTheme = 'light') { ... }
:- Cette fonction définit notre Custom Hook appelé
useTheme
. - Elle accepte un paramètre optionnel
initialTheme
, qui spécifie le thème initial (par défaut :'light'
).
- Cette fonction définit notre Custom Hook appelé
-
const [theme, setTheme] = useState(initialTheme);
:- Cette ligne initialise un état local appelé
theme
avec la valeur initiale passée (initialTheme
). setTheme
est une fonction permettant de mettre à jour cet état.
- Cette ligne initialise un état local appelé
-
useEffect(() => { ... }, []);
:- Cet effet secondaire s'exécute une seule fois au montage du composant.
- Il vérifie si un thème a été sauvegardé précédemment dans le
localStorage
. - Si un thème est trouvé, il met à jour l'état
theme
avec cette valeur.
-
localStorage.getItem('theme');
:- Cette méthode récupère la valeur du thème sauvegardée dans le
localStorage
. - Le
localStorage
est un mécanisme natif du navigateur qui permet de stocker des données persistantes.
- Cette méthode récupère la valeur du thème sauvegardée dans le
-
const toggleTheme = () => { ... };
:- Cette fonction permet de basculer entre le mode clair (
'light'
) et le mode sombre ('dark'
). - Elle met également à jour le
localStorage
pour garantir que le thème est conservé même après un rechargement de la page.
- Cette fonction permet de basculer entre le mode clair (
-
return [theme, toggleTheme];
:- Notre Custom Hook retourne un tableau contenant la valeur actuelle du thème (
theme
) et la fonction pour le basculer (toggleTheme
).
- Notre Custom Hook retourne un tableau contenant la valeur actuelle du thème (
-
import useTheme from './useTheme';
:- Dans notre composant principal (
App.js
), nous importons notre Custom HookuseTheme
.
- Dans notre composant principal (
-
const [theme, toggleTheme] = useTheme();
:- Nous utilisons notre Custom Hook pour initialiser l'état du thème (
theme
) et obtenir la fonction pour le basculer (toggleTheme
).
- Nous utilisons notre Custom Hook pour initialiser l'état du thème (
-
const styles = { ... };
:- Cette variable définit des styles conditionnels basés sur la valeur actuelle du thème.
backgroundColor
change dynamiquement selon que le thème est'light'
ou'dark'
.color
ajuste également la couleur du texte pour garantir un bon contraste.
-
<button onClick={toggleTheme}>Changer de thème</button>
:- Ce bouton appelle la fonction
toggleTheme
lorsqu'il est cliqué. - Cela bascule le thème entre
'light'
et'dark'
, tout en mettant à jour lelocalStorage
.
- Ce bouton appelle la fonction
5. Avantages des Custom Hooks
Les Custom Hooks offrent plusieurs avantages significatifs pour structurer et optimiser votre code React :
- Réutilisation de Logique : Encapsulez des fonctionnalités communes dans un Custom Hook pour les réutiliser facilement dans différents composants.
- Maintenabilité : Concentrez toute la logique liée à un aspect spécifique (par exemple, la gestion d'un thème) dans un seul endroit, rendant votre code plus facile à maintenir.
- Scalabilité : Les Custom Hooks simplifient la gestion de l'état et des effets secondaires complexes, ce qui est essentiel pour les applications React grandissantes.
- Optimisation des Performances : En combinant des Hooks comme
useState
etuseEffect
, vous pouvez éviter des duplications inutiles et améliorer les performances globales de votre application.
6. Meilleures Pratiques pour Créer des Custom Hooks
Pour créer des Custom Hooks efficaces et maintenables, voici quelques conseils pratiques :
- Nommez-les Correctement : Commencez toujours le nom de votre Custom Hook par
use
(ex.useCompteur
,useTheme
). Cela indique clairement qu'il s'agit d'un Hook personnalisé. - Gardez-les Réutilisables : Conçus vos Custom Hooks pour être utilisés dans différents contextes, sans dépendance excessive à un composant particulier.
- Testez-les Indépendamment : Avant de les intégrer dans vos composants principaux, testez vos Custom Hooks individuellement pour vous assurer qu'ils fonctionnent correctement.
- Documentez-les Bien : Ajoutez des commentaires ou une documentation explicite pour clarifier leur rôle et leur usage.
7. Cas d'Utilisation Courants pour les Custom Hooks
Les Custom Hooks sont particulièrement utiles dans les scénarios suivants :
- Gestion d'États Complexes : Par exemple, la gestion d'un panier d'achat ou d'une liste de tâches.
- Interactions avec le DOM : Encapsulez des interactions DOM récurrentes dans un Custom Hook pour les réutiliser facilement.
- Appels API : Créez un Custom Hook pour gérer les appels API, y compris le chargement et les erreurs.
- Gestion de Contextes : Comme illustré dans l'exemple précédent, les Custom Hooks peuvent simplifier la gestion de contextes comme les thèmes ou les informations utilisateur.
Conclusion
Vous avez maintenant appris à créer et utiliser des Custom Hooks en React. Ces Hooks personnalisés permettent de factoriser et de réutiliser des fonctionnalités complexes, rendant ainsi votre code plus maintenable, scalable et performant. Grâce aux Custom Hooks, vous pouvez encapsuler des logiques spécifiques (comme la gestion d'un compteur ou d'un thème) et les partager facilement entre plusieurs composants.
Prochain chapitre : Formulaires Avancés