Tutoriel React — Chapitre 12

Rendu conditionnel

Chapitre 12 — Rendu conditionnel

Jusqu’ici, vous avez surtout travaillé avec le state et les événements. Maintenant, on va découvrir un deuxième “pilier” de React : useEffect . useEffect sert à exécuter du code à certains moments : au chargement d’un composant, quand une valeur change, ou lors du nettoyage. On appelle cela des effets (side effects).

Objectif : comprendre (pas apprendre par cœur) Niveau : débutant absolu Pratique : mini-exercice à la fin

Plan du chapitre

1) Qu’est-ce qu’un “effet” ?

Un effet est un code qui interagit avec “l’extérieur” du rendu React. Le rendu React (le JSX) doit rester “pur” : il décrit l’UI. Un effet, lui, fait autre chose :

  • appeler une API
  • lire/écrire dans localStorage
  • mettre en place un timer (setInterval)
  • modifier le titre de la page (document.title)
  • abonner/désabonner un event listener

React sépare volontairement : rendu (UI) d’un côté, effets de l’autre.

2) Pourquoi React a besoin de useEffect

Dans un composant, le code se “ré-exécute” à chaque rendu. Si vous appelez une API directement dans le corps du composant, vous risquez d’appeler l’API à chaque re-render. Ce n’est pas ce qu’on veut.

Exemple à ne pas faire

export default function App() {
  // ❌ Appel direct pendant le rendu
  fetch("https://example.com/api");

  return <div>...</div>;
}

Ici, un re-render peut provoquer des appels multiples. useEffect permet de contrôler quand le code doit s’exécuter.

3) La syntaxe de base

useEffect prend deux arguments :

  • une fonction (le code à exécuter)
  • un tableau de dépendances (optionnel mais très important)
import { useEffect } from "react";

useEffect(() => {
  console.log("Effet exécuté");
}, []);

L’effet s’exécute après le rendu. React affiche d’abord l’UI, puis exécute l’effet.

4) Le tableau de dépendances : la règle qui change tout

Le tableau de dépendances indique à React quand relancer l’effet. Trois cas principaux :

A) Pas de tableau

useEffect(() => {
  console.log("À chaque rendu");
});

➡️ S’exécute après chaque rendu (souvent une mauvaise idée).

B) Tableau vide []

useEffect(() => {
  console.log("Une seule fois au montage");
}, []);

➡️ S’exécute une seule fois (comme “au chargement”).

C) Tableau avec dépendances

useEffect(() => {
  console.log("Quand count change");
}, [count]);

➡️ S’exécute au montage, puis à chaque fois que count change.

Règle simple : si l’effet utilise une valeur (state/prop) et que vous voulez réagir à ses changements, vous devez la mettre dans les dépendances.

5) Exécuter une fois au montage (comme “au chargement”)

Exemple : définir le titre de la page une seule fois.

import { useEffect } from "react";

export default function App() {
  useEffect(() => {
    document.title = "Mon application React";
  }, []);

  return <h1>Bienvenue</h1>;
}

6) Exécuter quand une valeur change

Exemple : mettre le titre à jour quand count change.

import { useEffect, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `Compteur : ${count}`;
  }, [count]);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount((c) => c + 1)}>+1</button>
    </div>
  );
}

Ici, l’effet s’exécute après le rendu initial, puis à chaque fois que count

7) Nettoyage (cleanup) : éviter les fuites

Certains effets mettent en place quelque chose qui doit être retiré quand le composant disparaît : un intervalle, un abonnement, un event listener, etc. Dans ce cas, useEffect peut retourner une fonction de nettoyage.

Exemple : setInterval

import { useEffect, useState } from "react";

export default function App() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setSeconds((s) => s + 1);
    }, 1000);

    // ✅ nettoyage quand le composant se démonte
    return () => clearInterval(id);
  }, []);

  return <p>Secondes : {seconds}</p>;
}

Sans cleanup, vous risquez d’avoir des “timers fantômes” qui continuent même quand le composant n’est plus affiché.

8) Cas pratiques : localStorage, timers

A) Lire au montage

useEffect(() => {
  const saved = localStorage.getItem("name");
  if (saved) setName(saved);
}, []);

B) Écrire quand une valeur change

useEffect(() => {
  localStorage.setItem("name", name);
}, [name]);

Exemple complet : un input contrôlé + persistance du prénom dans le navigateur.

9) Erreurs fréquentes

Mon effet tourne en boucle

Souvent, cela arrive quand l’effet modifie un state qui est dans les dépendances, et que cela déclenche une nouvelle exécution en permanence. Vérifiez vos dépendances et ce que vous mettez dans l’effet.

J’ai oublié les dépendances

Si votre effet utilise count ou name, mais que vous n’avez pas mis la dépendance correspondante, vous risquez d’avoir un comportement “pas à jour”.

Je ne comprends pas pourquoi l’effet se déclenche

Rappelez-vous : sans tableau → à chaque rendu. Tableau vide → 1 fois. Avec dépendances → quand ça change.

10) Résumé (à retenir)

  • useEffect sert à exécuter des effets (API, storage, timers…).
  • Il s’exécute après le rendu.
  • Dépendances : aucune → chaque rendu ; [] → 1 fois ; [x] → quand x change.
  • Le cleanup évite les fuites (interval, listeners…).

11) Exercice pratique (débutant)

Objectif : pratiquer les trois usages les plus courants de useEffect.

Partie A — Titre dynamique

  • Créez un compteur.
  • Avec useEffect, mettez à jour document.title avec la valeur du compteur.

Partie B — Persistance dans localStorage

  • Créez un input contrôlé “Prénom”.
  • Au montage, lisez localStorage.getItem("name") et remplissez le state si une valeur existe.
  • Quand le prénom change, sauvegardez-le dans localStorage.

Partie C — Timer

  • Créez un timer qui augmente un compteur de secondes toutes les 1 seconde.
  • Ajoutez le cleanup pour arrêter l’interval si le composant disparaît.

Prochaine étape : Chapitre 13, on va apprendre à faire des appels API (fetch) proprement et afficher des données externes.