Hooks Avancés : Créer et Utiliser des Hooks Personnalisés

8 min de lecture

1. Introduction aux Hooks Personnalisés

Les Hooks sont une fonctionnalité avancée introduite dans React 16.8 qui permet aux développeurs d'utiliser l'état et d'autres fonctionnalités de React sans avoir à écrire une classe. Plus spécifiquement, le term hooks personnalisés désigne les fonctions que nous écrivons nous-mêmes, qui peuvent utiliser des hooks à l'intérieur.

1.1 Qu’est-ce qu’un Hook personnalisé?

En termes simples, un hook personnalisé est une fonction JavaScript que vous écrivez vous-même nommée avec "use", qui peut utiliser les autres Hooks comme useState et useEffect pour encapsuler un comportement que vous voulez utiliser à nouveau. En pratique, ils servent souvent à masquer la complexité du code et à le rendre plus facile à comprendre. Ils offrent une approche plus propre et plus réutilisable pour partager non seulement l'état mais aussi la logique qui manipule cet état.

Voici un exemple simple d'un hook personnalisé:

1function useCustomHook(initialValue) {
2 const [value, setValue] = useState(initialValue);
3
4 // Logic goes here
5
6 return [value, setValue];
7}

1.2 Pourquoi utiliser des Hooks personnalisés?

L'une des principales raisons d'utiliser des Hooks personnalisés est la réutilisation de la logique d'état. Avant les Hooks, il était difficile de réutiliser la logique d'état entre les composants sans créer un composant plus grand contenant cette logique.

Cela signifie que vous pouvez extraire la logique des composants dans des fonctions réutilisables, tout en évitant les pièges habituels de rendus multiples ou de mises à jour d'état successives en dehors d'une opération de rendu. Plus d'informations peuvent être trouvées sur le blog officiel de React.

1.3 Les bases pour créer un Hook personnalisé

Pour créer un hook personnalisé, il vous suffit de définir une fonction nommée avec 'use' au début et c'est tout - cette fonction peut maintenant utiliser les autres Hooks. Il n'y a pas de règle stricte sur ce qu'un hook personnalisé doit faire exactement, il peut faire n'importe quoi de la mise en cache des données à la gestion d'un formulaire.

2. Logique de l'État dans les Hooks Personnalisés

L'un des plus grands atouts des hooks personnalisés est leur capacité à permettre la réutilisation de la logique d'état entre les composants. Cela peut prendre de nombreuses formes, des plus simples, comme la gestion d'une valeur unique avec useState, aux plus complexes, comme le contrôle de plusieurs valeurs interdépendantes avec useReducer.

2.1 Utiliser useState dans un Hook personnalisé

L’exemple le plus simple de l'utilisation de la logique d'état dans un hook personnalisé pourrait être l'utilisation du hook useState qui nous permet d'ajouter l'état React à une fonction de composant. Voici un exemple de hook personnalisé qui gère un simple compteur :

1function useCounter(initialValue) {
2 const [count, setCount] = useState(initialValue);
3
4 const increment = () => {
5 setCount(previousCount => previousCount + 1);
6 };
7
8 return { count, increment };
9}

Dans cet exemple, useCounter encapsule à la fois la valeur de l'état (count) et la fonction pour le modifier (increment). Nous pouvons utiliser ce hook personnalisé dans n'importe quel composant pour bénéficier d'un compteur réutilisable.

2.2 Gestion de plusieurs états avec useReducer

Le Hook useReducer est une alternative à useState qui s'avère utile lorsque nous avons une logique d'état complexe qui implique plusieurs sous-valeurs. Il vous permet également d'optimiser les performances pour les composants qui déclenchent des mises à jour d'état profondes, car vous pouvez transmettre du dispatch vers des composants plus profonds.

Un exemple de hook personnalisé utilisant useReducer pour gérer l'état d'un formulaire serait le suivant :

1function useLoginForm() {
2 const [state, dispatch] = useReducer(reducer, initialState);
3
4 const handleChange = (event) => {
5 dispatch({
6 type: "FIELD_CHANGE",
7 field: event.target.name,
8 value: event.target.value,
9 });
10 };
11
12 const handleSubmit = (event) => {
13 event.preventDefault();
14 // Logic for submitting the form
15 };
16
17 return { state, handleChange, handleSubmit };
18}

Dans cet exemple, le hook personnalisé useLoginForm gère l'ensemble de l'état d'un formulaire, y compris l'écoute des changements de champ et la soumission du formulaire.

3. Les Effets Secondaires dans les Hooks Personnalisés

Les hooks personnalisés ne se limitent pas à la réutilisation de la logique de l'état - ils peuvent également encapsuler la logique des effets secondaires à l'aide du Hook useEffect.

3.1 Utiliser useEffect dans un Hook personnalisé

Le Hook useEffect vous permet d'effectuer des effets secondaires dans les composants fonctionnels. Typiquement, il est utilisé pour les opérations qui sont communes à plusieurs composants : extraction de données, gestion des souscriptions, animation manuelle du DOM, etc.

Voici un exemple de Hook personnalisé qui utilise useEffect pour gérer un intervalle de temps :

1function useInterval(callback, delay) {
2 const savedCallback = useRef();
3
4 // Mémoriser la dernière callback.
5 useEffect(() => {
6 savedCallback.current = callback;
7 });
8
9 // Mettre en place l'intervalle.
10 useEffect(() => {
11 function tick() {
12 savedCallback.current();
13 }
14 if (delay !== null) {
15 let id = setInterval(tick, delay);
16 return () => clearInterval(id);
17 }
18 }, [delay]);
19}

Dans cet exemple, l'argument callback est la fonction que vous voulez appeler à chaque intervalle de temps (delay).

3.2 Gérer les effets secondaires liés à l’état

Avec l'utilisation du Hook useEffect, nous pouvons également gérer des effets secondaires comme gérer les modifications de l'état.

Par exemple, considérons un Hook personnalisé qui met à jour le titre du document chaque fois que la valeur de l'état change :

1function useDocumentTitle(title) {
2 useEffect(() => {
3 document.title = title;
4 }, [title]); // Mettre à jour le titre chaque fois que 'title' change
5}

Dans ce cas, chaque fois que 'title' change, le effet est rerendu, ce qui permet de mettre à jour dynamiquement le titre du document.

4. Réutilisation de la Logique avec les Hooks Personnalisés

L'une des principaux avantages des Hooks personnalisés est leur capacité à réemballer la logique en des modules réutilisables, ce qui vous permet d'éviter la duplication du code.

4.1 Partager la logique entre les composants

Phénoménalement, vous pouvez constater que la logique se répète dans plusieurs de vos composants. Par exemple, peut-être utilisez-vous des Hooks comme useState et useEffect ensemble pour extraire des données depuis une API. Si vous faites cela dans plus d'un endroit, alors vous êtes un candidat parfait pour extraire cette logique dans un hook personnalisé réutilisable.

Exemple d'un Hook personnalisé pour l'extraction de données

1function useDataFetcher(url) {
2 const [data, setData] = useState([]);
3 const [isLoading, setIsLoading] = useState(false);
4
5 useEffect(() => {
6 const fetchData = async () => {
7 setIsLoading(true);
8
9 const response = await fetch(url);
10 const data = await response.json();
11
12 setData(data);
13 setIsLoading(false);
14 };
15
16 fetchData();
17 }, [url]);
18
19 return { data, isLoading };
20}

Dans cet exemple, le Hook useDataFetcher peut être utilisé dans n'importe quel composant pour extraire des données depuis une URL spécifique.

4.2 Création d'une bibliothèque de Hooks personnalisés

Pour une meilleure organisation de votre code, vous pouvez créer une bibliothèque de Hooks personnalisés. Cela vous permet de regrouper tous vos Hooks personnalisés à un seul emplacement, ce qui facilite leur recherche et leur réutilisation.

Hook personnaliséUtilité
useFormGère l'ensemble de l'état d'un formulaire, y compris l'écoute des changements de champ et la soumission du formulaire.
useIntervalPermet de déclencher une fonction à des intervalles de temps réguliers.
useCounterFournit un compteur avec sa propre logique d'incrémentation.
useDataFetcherPermet d'extraire des données depuis une API donnée et gère l'état de chargement.

Ce tableau de votre bibliothèque de Hooks personnalisés n'est qu'un exemple des différents types de logiques que vous pouvez encapsuler dans des hooks personnalisés. La liste est infinie et dépend des spécificités de votre application.

5. Exemples Pratiques de Hooks Personnalisés

Il est courant dans le développement React de réutiliser la logique d'état et d'effets secondaires. Les Hooks personnalisés offrent une solution élégante pour factoriser et réutiliser cette logique à travers les composants. Voici quelques exemples pratiques qui illustrent comment on peut tirer parti des Hooks personnalisés dans divers contextes.

5.1 Un hook personnalisé pour fetcher des données

Considérons une situation où vous devez extraire des données depuis plusieurs endpoints API différents dans différents composants. Vous pouvez créer un Hook personnalisé qui encapsule la logique d'extraction de données.

1**javascript**
2function useFetch(url) {
3 const [data, setData] = useState(null);
4 const [isLoading, setIsLoading] = useState(true);
5
6 useEffect(() => {
7 async function fetchData() {
8 const response = await fetch(url);
9 const data = await response.json();
10 setData(data);
11 setIsLoading(false);
12 }
13 fetchData();
14 }, [url]);
15
16 return { data, isLoading };
17}

Dans ce Hook personnalisé, useFetch prend un url comme argument et renvoie un objet contenant les données extraites (data) et un booléen indiquant si les données sont encore en cours de chargement (isLoading). Vous pouvez maintenant utiliser ce Hook dans n'importe quel composant, lui passant simplement l'URL de l'API à extraire.

5.2 Un hook personnalisé pour gérer un formulaire

Les formulaires sont un autre domaine où les Hooks personnalisés peuvent grandement aider à réduire la duplication du code. Vous pouvez créer un Hook personnalisé pour gérer l'état d'un formulaire, les changements de champ, la validation, et la soumission du formulaire.

1**javascript**
2function useForm(initialValues) {
3 const [values, setValues] = useState(initialValues);
4
5 return [
6 values,
7 (e) => {
8 setValues({
9 ...values,
10 [e.target.name]: e.target.value,
11 });
12 },
13 ];
14}

Ce Hook personnalisé, useForm, prend en argument les initialValues de votre formulaire sous la forme d'un objet, et renvoie un tableau contenant l'état actuel du formulaire (values) et une fonction de gestion du changement de champ qui peut être directement passée à l'événement onChange de chaque champ de formulaire.

Ces deux exemples de Hooks personnalisés illustrent comment nous pouvons réutiliser efficacement la logique d'état et d'effets secondaires pour créer des applications React plus propres et plus maintenables.

6. Tests des Hooks Personnalisés

Tester vos Hooks personnalisés est aussi important que leur implémentation. Cela garantit que leur comportement est correct et qu'ils fonctionnent comme prévu. Vous pouvez utiliser Jest, un cadre de test populaire, et React Testing Library, une bibliothèque de test utile pour tester les composants React.

6.1 Installation et configuration de Jest

Pour commencer, vous devez installer Jest et React Testing Library. Vous pouvez le faire avec npm ou yarn :

1npm install --save jest @testing-library/react

ou

1yarn add jest @testing-library/react

Jest est pré-configuré pour effectuer des tests JavaScript, y compris des tests en React. Au lieu de tester les détails de l'implémentation d'un composant, les tests se concentreront sur le rendu correct du composant et le comportement attendu.

6.2 Écrire et exécuter des tests

Après avoir configuré Jest, vous pouvez commencer à écrire des tests pour vos Hooks. Avec React Testing Library, vous pouvez créer un composant de test qui utilise vos Hooks, puis rendre ce composant dans le test pour inspecter et interagir avec lui.

Admettons que nous voulions tester le Hook useCounter que nous avons défini précédemment. Nous pourrions créer un test ressemblant à ceci :

1test('useCounter custom hook', () => {
2 function TestComponent() {
3 const { count, increment } = useCounter(0);
4
5 return (
6 <div>
7 <button onClick={increment}>Incrémenter</button>
8 <p>{count}</p>
9 </div>
10 );
11 }
12
13 const { getByText } = render(<TestComponent />);
14 const count = getByText('0');
15 const incrementButton = getByText("Incrémenter");
16
17 expect(count).toHaveTextContent('0');
18
19 fireEvent.click(incrementButton);
20
21 expect(count).toHaveTextContent('1');
22});

Dans ce code, nous testons si le compteur affiche initialement '0' et s'incrémente correctement après que le bouton "Incrémenter" a été cliqué. Pour exécuter les tests, vous pouvez simplement exécuter la commande jest dans votre terminal.

7. Les erreurs courantes à éviter lors de la création des Hooks personnalisés

La création de Hooks personnalisés est un excellent moyen d'encapsuler et de réutiliser la logique dans vos applications React. Cependant, il y a certaines erreurs courantes que vous devez éviter pour éviter des comportements imprévus.

7.1 L’imbrication des hooks

Les Hooks sont conçus pour être appelés au niveau supérieur de vos composants React. L'imbrication des Hooks à l'intérieur des boucles, des conditions ou des fonctions imbriquées est un écueil courant qui peut conduire à des bugs difficiles à repérer.

Assurez-vous toujours de respecter les règles d'utilisation des Hooks décrites dans la documentation officielle. Utilisez le plugin ESLint eslint-plugin-react-hooks pour vous aider à surveiller et à appliquer ces règles.

7.2 La dépendance excessive aux Hooks personnalisés

Bien que les Hooks personnalisés soient une fonctionnalité puissante, ils ne doivent pas être surexploités. Considérez toujours si la logique de votre composant peut être simplifiée sans l'utilisation de Hooks personnalisés.

Il est également important de faire attention à ne pas créer des dépendances inutiles entre vos Hooks personnalisés. Cela pourrait faire de votre code un labyrinthe difficile à naviguer et à maintenir.

7.3 L'utilisation incorrecte des dépendances de l’effet

Lors de l'utilisation du Hook useEffect, assurez-vous d'inclure toutes les dépendances externes utilisées dans votre effet dans le tableau de dépendances. Omettre une dépendance qui change au fil du temps peut provoquer des bugs étranges et des effets qui se comportent de manière inattendue.

Cela est particulièrement vrai lorsque vous utilisez des Hooks personnalisés à l'intérieur de useEffect. Assurez-vous d'inclure tous les retours de vos Hooks personnalisés dans le tableau de dépendances de votre effet.


En suivant ces conseils et en évitant ces erreurs courantes, vous pouvez maximiser les avantages des Hooks personnalisés tout en minimisant les surprises désagréables.

8. Conclusion

En somme, l'utilisation des Hooks personnalisés dans React offre des avantages significatifs en termes d'encapsulation de la logique et de réusabilité du code. Ils apportent une meilleure organisation du code, facilitant le développement et la maintenance de votre application.

8.1 Les bénéfices de l'utilisation des hooks personnalisés

Les Hooks personnalisés jouent un rôle clé dans la réduction de la duplication du code et la création d'un code plus propre et facile à comprendre. Leur capacité à extraire et partager la logique d'état et d'effets entre des composants différents facilite la réutilisation du code et améliore l'efficacité du développement.

8.2 Quand utiliser un Hook personnalisé

Il est judicieux d'utiliser un Hook personnalisé lorsque la même logique est utilisée dans plusieurs composants, ou lorsque cette logique est suffisamment complexe pour justifier son extraction dans une fonction réutilisable. Le Hook personnalisé permet non seulement de séparer la logique du rendu, mais offre également une plus grande flexibilité et une meilleure structuration du code.

8.3 Perspectives futures de l'utilisation des Hooks personnalisés

Les Hooks personnalisés ne sont que le début. Avec l'expansion constante de l'écosystème React, on peut s'attendre à voir apparaître de nombreux autres patterns et abstractions pour les Hooks. Il est donc essentiel de continuer à explorer et à apprendre les idées avancées autour des Hooks personnalisés et l'évolution de la communauté React.

En fin de compte, le pouvoir des Hooks personnalisés réside dans leur simplicité et le potentiel illimité qu'ils offrent pour encapsuler et réutiliser n'importe quelle logique dans vos applications React. Alors n'hésitez pas à essayer, expérimenter et créer vos propres Hooks personnalisés.

5.0 (38 notes)

Cet article vous a été utile ? Notez le