BaliseTonSite

useEffect & Cycle de Vie

Gère les effets de bord : appels API, timers, abonnements...

5.1Qu'est-ce qu'un effet de bord ?

Tout ce qui n'est pas "calculer du JSX" est un effet de bord :

  • Appeler une API (fetch)
  • Manipuler le DOM (document.title)
  • Lancer un timer (setInterval, setTimeout)
  • S'abonner à un WebSocket ou un événement
  • Lire le localStorage

Ces opérations ne peuvent pas se faire pendant le rendu. Elles doivent se faire après que React a affiché le composant. C'est le rôle de useEffect.

5.2Syntaxe de useEffect

TSXtsx
import { useEffect } from 'react'

useEffect(() => {
  // Code exécuté APRÈS le rendu
  // (l'effet)

  return () => {
    // Code exécuté au DÉMONTAGE
    // (le cleanup, optionnel)
  }
}, [/* dépendances */])

Le tableau de dépendances contrôle quand l'effet se relance :

DépendancesQuand l'effet relanceCas d'usage
[] (vide)1 seule fois (au montage)Fetch initial, abonnement
[count]Quand count changeRéaction à un state
Pas de tableauÀ chaque renduRarement voulu

5.3Exemple : appel API

Le cas d'usage le plus courant : charger des données depuis une API quand le composant apparaît :

TSXtsx
import { useState, useEffect } from 'react'

function ListeUtilisateurs() {
  const [users, setUsers] = useState([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    async function fetchUsers() {
      try {
        const res = await fetch('https://jsonplaceholder.typicode.com/users')
        if (!res.ok) throw new Error('Erreur réseau')
        const data = await res.json()
        setUsers(data)
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Erreur inconnue')
      } finally {
        setLoading(false)
      }
    }

    fetchUsers()
  }, [])  // [] = s'exécute UNE seule fois au montage

  if (loading) return <p>Chargement...</p>
  if (error) return <p>Erreur : {error}</p>

  return (
    <ul>
      {users.map((user: any) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  )
}

5.4Effet avec dépendances

L'effet se relance quand une de ses dépendances change :

TSXtsx
function RechercheProduits() {
  const [query, setQuery] = useState("")
  const [resultats, setResultats] = useState([])

  useEffect(() => {
    if (query.length < 2) {
      setResultats([])
      return
    }

    // Recherche quand la query change (avec debounce natif)
    const timer = setTimeout(async () => {
      const res = await fetch(`/api/search?q=${query}`)
      const data = await res.json()
      setResultats(data)
    }, 300)

    // Cleanup : annule le timer si query re-change vite
    return () => clearTimeout(timer)
  }, [query])  // ← Se relance quand 'query' change

  return (
    <div>
      <input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Rechercher..."
      />
      <ul>
        {resultats.map((r: any) => (
          <li key={r.id}>{r.name}</li>
        ))}
      </ul>
    </div>
  )
}

5.5Le cleanup : nettoyer après soi

Si ton effet crée quelque chose (timer, abonnement, event listener), tu dois le nettoyer quand le composant disparaît :

TSXtsx
function Horloge() {
  const [heure, setHeure] = useState(new Date())

  useEffect(() => {
    const interval = setInterval(() => {
      setHeure(new Date())
    }, 1000)

    // Cleanup : arrête le timer quand le composant disparaît
    return () => clearInterval(interval)
  }, [])

  return <p>Il est {heure.toLocaleTimeString()}</p>
}

// Avec un event listener
function TailleEcran() {
  const [width, setWidth] = useState(window.innerWidth)

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth)
    window.addEventListener('resize', handleResize)

    return () => window.removeEventListener('resize', handleResize)
  }, [])

  return <p>Largeur : {width}px</p>
}

Verifie tes acquis

3 questions pour valider ce chapitre

1. Quand s'execute un useEffect sans tableau de dependances ?

Valide et sauvegarde ce chapitre

Ne perds pas le fil de ton apprentissage. Chaque QCM terminé sauvegarde ton score. Crée ton profil gratuitement pour débloquer toutes les évaluations du site et retrouver tes résultats plus tard.

Commencer l'aventure
Déjà membre ?Connecte-toi