WabTechs
AccueilBlogDocumentationProjetsPodcastVidéosCommunauté
ConnexionS'inscrire
WabTechs
Quick Link
  • Service
  • Projects
  • Pricing
  • FAQs
  • Contact
Adresse
  • n° 27 bis Katakombe 2 Ngalima Kinshasa RDC
  • contact@wabtechs.com
  • +243 850 060 060

Copyright ©2026, Wabtechs Company All Rights Reserved

GitHubTwitterYouTubeLinkedIn
BlogReact Hooks : Patterns avancés pour la production
Retour au blog
React
Hooks
TypeScript

React Hooks : Patterns avancés pour la production

Découvrez les patterns de hooks les plus utiles — debounce, localStorage, media queries, et custom hooks réutilisables.

Emmanuel Mulonda5 juillet 20268 min de lecture

Introduction

Les hooks sont le cœur de React. Voici les patterns que j'utilise dans chaque projet de production.

useDebounce

Délayez une valeur pour éviter les appels API excessifs :

import { useState, useEffect } from "react";

export function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

// Usage
const [search, setSearch] = useState("");
const debouncedSearch = useDebounce(search, 300);

useLocalStorage

Persistance dans le localStorage avec typage :

import { useState, useEffect } from "react";

export function useLocalStorage<T>(key: string, initialValue: T) {
  const [value, setValue] = useState<T>(() => {
    if (typeof window === "undefined") return initialValue;
    try {
      const item = window.localStorage.getItem(key);
      return item ? (JSON.parse(item) as T) : initialValue;
    } catch {
      return initialValue;
    }
  });

  useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue] as const;
}

useMediaQuery

Écoutez les changements de viewport :

import { useEffect, useState } from "react";

export function useMediaQuery(query: string): boolean {
  const [matches, setMatches] = useState(() => {
    if (typeof window === "undefined") return false;
    return window.matchMedia(query).matches;
  });

  useEffect(() => {
    const media = window.matchMedia(query);
    const listener = (e: MediaQueryListEvent) => setMatches(e.matches);
    media.addEventListener("change", listener);
    return () => media.removeEventListener("change", listener);
  }, [query]);

  return matches;
}

// Usage
const isMobile = useMediaQuery("(max-width: 768px)");
const prefersDark = useMediaQuery("(prefers-color-scheme: dark)");

useIntersectionObserver

Détection de visibilité pour le lazy loading :

import { useEffect, useRef, useState } from "react";

export function useIntersectionObserver(threshold = 0.1) {
  const ref = useRef<HTMLDivElement>(null);
  const [isVisible, setIsVisible] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setIsVisible(true);
          observer.disconnect();
        }
      },
      { threshold },
    );

    if (ref.current) observer.observe(ref.current);
    return () => observer.disconnect();
  }, [threshold]);

  return { ref, isVisible };
}

useFetch

Wrapper fetch avec loading, error et data :

React
Hooks
TypeScript
Partager :

Table des matières

  • Introduction
  • useDebounce
  • useLocalStorage
  • useMediaQuery
  • useIntersectionObserver
  • useFetch
  • useTimeout
  • Règles d'Or
  • Conclusion

Articles similaires

Next.js
React
12 min
Composants serveur React : le guide pratique
Server Components, directives, sérialisation : comment tirer le meilleur de l'architecture moderne de React 19 et Next.js 16.

17 juillet 2026

TypeScript
Prisma
10 min
Prisma ou Drizzle : comment choisir votre ORM en 2026
Les deux ORM TypeScript dominent l'écosystème. Comparaison honnête sur la DX, la performance, les migrations et la sécurité des types.
import { useState, useEffect } from "react";

export function useFetch<T>(url: string) {
  const [data, setData] = useState<T | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const controller = new AbortController();

    fetch(url, { signal: controller.signal })
      .then((res) => res.json())
      .then(setData)
      .catch((err) => {
        if (err.name !== "AbortError") setError(err.message);
      })
      .finally(() => setLoading(false));

    return () => controller.abort();
  }, [url]);

  return { data, error, loading };
}

useTimeout

Exécution différée avec cleanup automatique :

import { useEffect, useRef } from "react";

export function useTimeout(callback: () => void, delay: number | null) {
  const callbackRef = useRef(callback);
  callbackRef.current = callback;

  useEffect(() => {
    if (delay === null) return;
    const timer = setTimeout(() => callbackRef.current(), delay);
    return () => clearTimeout(timer);
  }, [delay]);
}

Règles d'Or

  1. Nommez vos hooks avec le préfixe use
  2. Ne conditionnez pas les appels de hooks
  3. Utilisez les dépendances correctement dans useEffect
  4. Nettoyez toujours les side effects
  5. Extrayez les hooks personnalisés quand la logique se répète

Conclusion

Ces hooks sont la base de tout projet React solide. Réutilisez-les, adaptez-les, et n'hésitez pas à en créer de nouveaux quand le besoin se présente.

24 juillet 2026

Next.js
Architecture
8 min
Construire une architecture scalable avec Next.js App Router
Découvrez les patterns avancés pour structurer vos applications Next.js en production.

15 juillet 2026