🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

React useEffect Infinite Loop: Por que isso acontece e exatamente como corrigi-lo

⏱️5 min read  ·  1,097 words

{
“@context”: “https://schema.org”,
“@type”: “TechArticle”,
“headline”: “React useEffect Infinite Loop: Por que isso acontece e exatamente como corrigi-lo”,
“description”: “Guia completo para diagnosticar e corrigir loops infinitos React useEffect – erros de matriz de dependência, dependências de objeto/função e todos os padrões comuns.”,
“url”: “https://techpulsesite.com/react-useeffect-infinite-loop-why-it-hap-pt/”,
“datePublished”: “2026-06-25T16:35:00+00:00”,
“dateModified”: “2026-06-29T04:14:41+00:00”,
“author”: {
“@type”: “Organization”,
“name”: “TechPulse Editorial Team”,
“url”: “https://techpulsesite.com”
},
“publisher”: {
“@type”: “Organization”,
“name”: “TechPulse”,
“url”: “https://techpulsesite.com”
},
“inLanguage”: “pt”
}

{
“@context”: “https://schema.org”,
“@type”: “TechArticle”,
“headline”: “React useEffect Infinite Loop: Por que isso acontece e exatamente como corrigi-lo”,
“description”: “Guia completo para diagnosticar e corrigir loops infinitos React useEffect – erros de matriz de dependência, dependências de objeto/função e todos os padrões comuns.”,
“url”: “https://techpulsesite.com/react-useeffect-infinite-loop-why-it-hap-pt/”,
“datePublished”: “2026-06-25T16:35:00+00:00”,
“dateModified”: “2026-06-21T05:59:37+00:00”,
“author”: {
“@type”: “Organization”,
“name”: “TechPulse Editorial Team”,
“url”: “https://techpulsesite.com”
},
“publisher”: {
“@type”: “Organization”,
“name”: “TechPulse”,
“url”: “https://techpulsesite.com”
},
“inLanguage”: “pt”
}

A Reagir useEffect loop infinito é um dos bugs mais comuns para desenvolvedores aprenderem ganchos. Seu componente é renderizado novamente, aciona o efeito, o que causa outra renderização, que aciona o efeito novamente – até que o navegador trave. Veja por que isso acontece e exatamente como corrigir cada variante.

Por que os loops infinitos acontecem

Cada nova renderização de um componente React cria novas referências para objetos, arrays e funções definidas dentro do componente. Se o seuuseEffect dependency array contém um desses valores, o React vê uma “nova” dependência em cada renderização – mesmo que os dados sejam logicamente idênticos – e executa o efeito novamente, causando outra nova renderização, criando outro loop.

Causa 1: Definir estado sem dependências (mais comum)

// 🐛 Bug: runs after every render, sets state, causes re-render
useEffect(() => {
  setCount(count + 1); // state update → re-render → effect runs again
}); // no dependency array = runs after EVERY render

// ✅ Fix: empty dependency array = run once on mount only
useEffect(() => {
  setCount(prevCount => prevCount + 1);
}, []); // runs once

Causa 2: Objeto na matriz de dependência

// 🐛 Bug: new object reference on every render
function UserProfile({ userId }) {
  const options = { method: 'GET', headers: { 'Auth': 'token' } }; // NEW object each render

  useEffect(() => {
    fetchUser(userId, options);
  }, [options]); // options is always "new" → infinite loop
}

// ✅ Fix 1: move object outside component (if it's static)
const OPTIONS = { method: 'GET', headers: { 'Auth': 'token' } }; // defined once

function UserProfile({ userId }) {
  useEffect(() => {
    fetchUser(userId, OPTIONS);
  }, [userId]); // only depends on userId
}

// ✅ Fix 2: useMemo if the object depends on props
function UserProfile({ userId, token }) {
  const options = useMemo(
    () => ({ method: 'GET', headers: { 'Auth': token } }),
    [token] // only recreates when token changes
  );

  useEffect(() => {
    fetchUser(userId, options);
  }, [userId, options]);
}

Causa 3: Função na matriz de dependência

// 🐛 Bug: new function reference on every render
function DataFetcher({ id }) {
  const fetchData = async () => { // NEW function each render
    const data = await api.get(id);
    setData(data);
  };

  useEffect(() => {
    fetchData();
  }, [fetchData]); // fetchData is always "new" → infinite loop
}

// ✅ Fix: useCallback to memoize the function
function DataFetcher({ id }) {
  const fetchData = useCallback(async () => {
    const data = await api.get(id);
    setData(data);
  }, [id]); // only recreates when id changes

  useEffect(() => {
    fetchData();
  }, [fetchData]); // stable reference now
}

// ✅ Alternative: define function INSIDE the effect
useEffect(() => {
  const fetchData = async () => {
    const data = await api.get(id);
    setData(data);
  };
  fetchData();
}, [id]); // clean, no useCallback needed

Causa 4: Atualização de estado com estado como dependência

// 🐛 Bug: count is dependency AND being updated inside effect
useEffect(() => {
  const timer = setInterval(() => {
    setCount(count + 1); // depends on count → loop
  }, 1000);
  return () => clearInterval(timer);
}, [count]); // re-runs every time count changes

// ✅ Fix: use functional state update (no dependency on count)
useEffect(() => {
  const timer = setInterval(() => {
    setCount(prev => prev + 1); // no dependency on count needed
  }, 1000);
  return () => clearInterval(timer);
}, []); // runs once, updates count independently

Causa 5: Matriz em Matriz de Dependência

// 🐛 Bug: new array reference on every render
function List({ items }) {
  const filtered = items.filter(i => i.active); // NEW array each render

  useEffect(() => {
    processItems(filtered);
  }, [filtered]); // always "new" → infinite loop
}

// ✅ Fix: useMemo to stabilize the array
function List({ items }) {
  const filtered = useMemo(
    () => items.filter(i => i.active),
    [items]
  );

  useEffect(() => {
    processItems(filtered);
  }, [filtered]);
}

Como depurar qualquer loop infinito

  1. Adicione console.log antes de useEffect: Veja com que frequência o componente é renderizado novamente.
  2. Comente a atualização do estado dentro do efeito: Se o loop parar, a atualização do estado é a causa.
  3. Registre cada dependência: console.log('dep1:', dep1, 'dep2:', dep2) dentro do efeito para ver qual deles mudou.
  4. Use o plugin ESLint react-hooks: eslint-plugin-react-hooks sinaliza dependências ausentes automaticamente.

Referência rápida: quando usar cada gancho

Gancho Usar para
usarEfeito Efeitos colaterais: busca de dados, assinaturas, manipulação de DOM
useMemorando Valores computados caros — impedem o recálculo em cada renderização
useCallback Funções passadas como dependências ou props para filhos memorizados
usarRef Valores que não devem acionar novas renderizações quando alterados

Perguntas Frequentes

P: Quando devo usar uma matriz de dependência vazia?
R: Quando o efeito deve ser executado apenas uma vez na montagem (por exemplo, buscar dados iniciais, configurar uma assinatura). Tenha cuidado – isso cria um fechamento sobre os valores do estado inicial.

P: Devo sempre incluir tudo na matriz de dependências?
R: Sim, de acordo com as regras do React. Se incluir algo causar um loop, a verdadeira solução é estabilizar esse valor com useMemo/useCallback, não removê-lo das dependências.

P: Qual é a diferença entre useMemo e useCallback?
A: useMemo memoiza um valor (por exemplo, uma matriz filtrada). useCallback memoriza uma função. Ambos evitam recriações desnecessárias em cada renderização.

P: Por que o React executa useEffect duas vezes durante o desenvolvimento?
R: O React 18 Strict Mode executa efeitos duas vezes intencionalmente no desenvolvimento para ajudar a encontrar efeitos colaterais que não são eliminados corretamente. Isso não acontece na produção.

P: Posso desabilitar a regra de dependências exaustivas do ESLint?
R: Você pode, mas não deveria. A regra existe porque dependências ausentes causam bugs sutis. Corrija o problema subjacente em vez de desativar o aviso.

Conclusão

Os loops infinitos do React useEffect sempre se resumem a uma causa raiz:uma dependência que cria uma nova referência em cada renderização, fazendo com que o efeito seja executado novamente, o que aciona outra renderização. A correção é sempre estabilizar essa referência usandouseMemo, useCallback, useRefou movendo o valor para fora do componente. Depois de internalizar o modelo mental “mesma referência = sem nova execução”, esses bugs se tornam fáceis de prevenir e rápidos de depurar.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা