{
“@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.
📋 Table of Contents
- Por que os loops infinitos acontecem
- Causa 1: Definir estado sem dependências (mais comum)
- Causa 2: Objeto na matriz de dependência
- Causa 3: Função na matriz de dependência
- Causa 4: Atualização de estado com estado como dependência
- Causa 5: Matriz em Matriz de Dependência
- Como depurar qualquer loop infinito
- Referência rápida: quando usar cada gancho
- Perguntas Frequentes
- Conclusão
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
- Adicione console.log antes de useEffect: Veja com que frequência o componente é renderizado novamente.
- Comente a atualização do estado dentro do efeito: Se o loop parar, a atualização do estado é a causa.
- Registre cada dependência:
console.log('dep1:', dep1, 'dep2:', dep2)dentro do efeito para ver qual deles mudou. - Use o plugin ESLint react-hooks:
eslint-plugin-react-hookssinaliza 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.
🔗 Share this article
✍️ Leave a Comment