Un composant React doit être pur : il calcule du JSX à partir de ses props/state. Tout le reste est un effet de bord :
document.title)useEffect permet d'exécuter ces effets après le rendu.
const { useEffect, useState } = React;
useEffect(() => {
// Code exécuté après le rendu
console.log('Effet exécuté !');
});
| Syntaxe | Quand l'effet s'exécute |
|---|---|
useEffect(() => { ... }) |
Après chaque rendu (rarement souhaité) |
useEffect(() => { ... }, []) |
Uniquement au montage (1 seule fois) |
useEffect(() => { ... }, [a, b]) |
Au montage + quand a ou b change |
useEffect(() => {
console.log('Rendu effectué');
});
// ⚠️ S'exécute à CHAQUE rendu — rarement ce qu'on veut
[] — au montage uniquementuseEffect(() => {
console.log('Composant monté !');
// Parfait pour : fetch initial, setup
}, []);
// Ne s'exécute qu'UNE seule fois
[dep1, dep2]useEffect(() => {
document.title = `Compteur : ${count}`;
}, [count]);
// S'exécute au montage + quand "count" change
L'effet peut retourner une fonction de nettoyage, appelée quand le composant se démonte ou avant la ré-exécution de l'effet :
useEffect(() => {
// Setup
const timer = setInterval(() => {
console.log('tick');
}, 1000);
// Cleanup — appelé au démontage
return () => {
clearInterval(timer);
console.log('Timer nettoyé');
};
}, []);
Montage (1er rendu)
→ Effet exécuté (setup)
Mise à jour (re-rendu si dépendance change)
→ Cleanup de l'ancien effet
→ Nouvel effet exécuté
Démontage (composant retiré)
→ Cleanup final
function ListeUsers() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [erreur, setErreur] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => {
if (!res.ok) throw new Error('Erreur réseau');
return res.json();
})
.then(data => {
setUsers(data);
setLoading(false);
})
.catch(err => {
setErreur(err.message);
setLoading(false);
});
}, []); // [] = une seule fois au montage
if (loading) return <p>Chargement...</p>;
if (erreur) return <p>Erreur : {erreur}</p>;
return (
<ul>
{users.map(u => <li key={u.id}>{u.name}</li>)}
</ul>
);
}
async directement sur le callback de useEffect :
// ❌ INTERDIT
useEffect(async () => { ... }, []);
// ✅ Créer une fonction async à l'intérieur
useEffect(() => {
const fetchData = async () => {
const res = await fetch(url);
const data = await res.json();
setData(data);
};
fetchData();
}, []);
▼ useEffect en action : timer, titre, fetch
useEffect(fn) — après chaque rendu.useEffect(fn, []) — au montage uniquement.useEffect(fn, [dep]) — au montage + quand dep change.async directement sur le callback.