DEV Community

ahmed SENEINA
ahmed SENEINA

Posted on • Originally published at gogokodo.com

useEffect Boucle Infinie en React : 5 Causes et Comment les Corriger

Ta console explose de logs, ton navigateur ralentit, l'onglet freeze — tu es face à une boucle infinie useEffect. C'est le bug React le plus frustrant pour les débutants. Voici les 5 causes et comment les corriger.

Comment détecter une boucle infinie

  • Console qui spam : des centaines de logs identiques
  • Erreur React : Too many re-renders.
  • Navigateur qui rame : 100% CPU
  • Network : dizaines de fetch identiques

Cause 1 : Pas de tableau de dépendances

// ❌ S'exécute à CHAQUE rendu
useEffect(() => {
  fetch('/api/data').then(r => r.json()).then(setData);
}); // pas de []

// ✅ Une seule fois au montage
useEffect(() => {
  fetch('/api/data').then(r => r.json()).then(setData);
}, []); // tableau vide
Enter fullscreen mode Exit fullscreen mode

Cause 2 : setState avec la valeur dans les deps

// ❌ count change → useEffect → setCount → 💥
const [count, setCount] = useState(0);
useEffect(() => {
  setCount(count + 1);
}, [count]);

// ✅ Forme fonctionnelle
useEffect(() => {
  const timer = setInterval(() => {
    setCount(prev => prev + 1);
  }, 1000);
  return () => clearInterval(timer);
}, []);
Enter fullscreen mode Exit fullscreen mode

Cause 3 : Objet/array dans les dépendances

// ❌ Nouvel objet à chaque rendu = nouvelle référence
const options = { query, limit: 10 };
useEffect(() => {
  fetchResults(options);
}, [options]); // 💥

// ✅ Dépendre des primitives
useEffect(() => {
  fetchResults({ query, limit: 10 });
}, [query]); // string = stable
Enter fullscreen mode Exit fullscreen mode

Cause 4 : Fonction qui recrée un objet

// ❌
useEffect(() => {
  fetch(\`/api?\${new URLSearchParams(getFilters())}\`);
}, [getFilters()]); // nouvel objet = 💥

// ✅ Constante
const FILTERS = { category: 'tech' };
useEffect(() => {
  fetch(\`/api?\${new URLSearchParams(FILTERS)}\`);
}, []);
Enter fullscreen mode Exit fullscreen mode

Cause 5 : Fetch → setState → re-render → fetch

// ❌ url change dans l'effet qui dépend de url
useEffect(() => {
  fetch(url).then(r => r.json()).then(result => {
    setData(result);
    setUrl(result.nextPage); // change url → relance 💥
  });
}, [url]);

// ✅ url ne change que sur action utilisateur
useEffect(() => {
  fetch(url).then(r => r.json()).then(setData);
}, [url]);
const loadMore = () => setUrl(data.nextPage); // clic
Enter fullscreen mode Exit fullscreen mode

La règle d'or

Si tu peux calculer une valeur sans useEffect, ne l'utilise pas.

// ❌ useEffect pour du state dérivé
useEffect(() => {
  setTotal(items.reduce((s, i) => s + i.price, 0));
}, [items]);

// ✅ Calcul direct
const total = items.reduce((s, i) => s + i.price, 0);
Enter fullscreen mode Exit fullscreen mode

Article original sur gogokodo.com

Top comments (0)