Um error boundary é um componente React que captura erros lançados durante a renderização dos componentes dentro dele e mostra uma UI alternativa em vez de derrubar o app inteiro. Ele precisa ser um componente de classe que define static getDerivedStateFromError, porque não existe hook para isso. Você o escreve uma vez e o coloca em volta de qualquer parte da árvore.
Aperte "Break the profile" para fazer o filho lançar um erro durante a renderização.
O perfil é substituído pelo fallback, e o resto da página continua funcionando. O console mostra o erro duas vezes: o React registra todo erro capturado com console.error, e o componentDidCatch o registra de novo. "Try again" limpa a causa (broken) e o erro do boundary, então o perfil renderiza de novo. Remova this.props.onReset(); de reset e o Try again volta direto para o fallback, porque nada corrigiu a causa.
Como a classe funciona
Dois métodos tornam uma classe um error boundary:
static getDerivedStateFromError(error)executa durante a renderização, logo depois que um filho lança um erro. Ele retorna a atualização de estado que troca o boundary para o fallback. Ele precisa ser puro: nada de logs, nada de requisições.componentDidCatch(error, info)executa depois que o fallback está na tela. Use-o para efeitos colaterais como enviar o erro para um serviço de monitoramento.info.componentStacklista o componente que lançou o erro e os componentes acima dele.
class ErrorBoundary extends Component {
state = { error: null };
static getDerivedStateFromError(error) {
return { error }; // switch to the fallback
}
componentDidCatch(error, info) {
reportError(error, info.componentStack); // your logging service
}
render() {
if (this.state.error) return this.props.fallback;
return this.props.children;
}
}
Não existe equivalente em hook, então mesmo um app escrito só com componentes de função precisa dessa única classe. A página sobre componentes de classe explica a sintaxe de classes, se ela for nova para você.
O que um boundary captura, e o que não captura
Um boundary captura erros que acontecem enquanto o React trabalha nos componentes dentro dele:
- renderização (o corpo de um componente de função, o
renderde uma classe), - métodos de ciclo de vida e construtores de componentes de classe filhos,
- efeitos (
useEffect,useLayoutEffect) e ref callbacks, - uma promise rejeitada lida com use e, no React 19, um erro lançado por uma form action ou por uma função passada para o
startTransitiondouseTransition.
Ele não captura:
- erros em event handlers,
- código assíncrono que você mesmo inicia:
setTimeout, callbacks de.then(), umawaitem um event handler, - erros no próprio
renderdo boundary (o próximo boundary acima os captura), - erros durante a renderização no servidor.
Os event handlers ficam de fora porque não quebram a renderização. A tela continua em um estado válido, então um try/catch no handler basta. Se você quiser que o boundary apareça, guarde o erro no estado e lance-o na próxima renderização:
O primeiro botão deixa os botões na tela e só imprime um erro não capturado no console. O segundo captura a rejeição, guarda-a, e o boundary assume.
Onde colocar boundaries
Um boundary em volta do app inteiro evita a tela branca, mas aí qualquer erro pequeno substitui tudo. Coloque boundaries em volta de partes que podem falhar de forma independente: um widget da barra lateral, um gráfico, cada rota. Uma falha então custa ao usuário um painel, não a página.
Só o painel Stocks mostra o fallback. Coloque os dois widgets em um único <ErrorBoundary> e o painel Weather, que funciona, some junto.
Sem nenhum boundary, o React remove a árvore inteira da tela quando um erro de renderização não é capturado. Uma página vazia é mais segura do que uma quebrada mostrando dados errados, mas os usuários a interpretam como um travamento.
A biblioteca react-error-boundary
O pacote react-error-boundary envolve a classe para você e adiciona auxiliares de reinicialização. Ele não está disponível neste editor, então aparece aqui em um bloco estático:
import { ErrorBoundary, useErrorBoundary } from 'react-error-boundary';
function Fallback({ error, resetErrorBoundary }) {
return (
<div role="alert">
<p>Something went wrong: {error.message}</p>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
);
}
<ErrorBoundary FallbackComponent={Fallback} onReset={() => refetch()} resetKeys={[userId]}>
<Profile userId={userId} />
</ErrorBoundary>;
// Inside a child: hand an async error to the boundary
const { showBoundary } = useErrorBoundary();
fetchData().catch(showBoundary);
resetKeys reinicia o boundary quando qualquer valor listado muda, e showBoundary faz o truque de "guardar e lançar" do exemplo anterior.
Reportando erros no React 19
O React 19 reporta erros de um jeito novo. Erros capturados por um boundary são registrados uma vez com console.error, e erros não capturados vão para window.reportError. Para enviá-los ao seu próprio serviço, passe opções para createRoot. Cada opção substitui o registro padrão correspondente:
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'), {
onCaughtError(error, errorInfo) {
// an error boundary caught it
logToService('caught', error, errorInfo.componentStack);
},
onUncaughtError(error, errorInfo) {
// no boundary caught it, and React removed the tree
logToService('uncaught', error, errorInfo.componentStack);
},
onRecoverableError(error, errorInfo) {
// React recovered by itself, for example after a hydration mismatch
logToService('recovered', error, errorInfo.componentStack);
},
});
root.render(<App />);
onRecoverableError é para erros que o React corrigiu sem a sua ajuda, como uma divergência de hidratação ou um erro de renderização que sumiu quando o React tentou de novo. O hydrateRoot aceita as mesmas três opções.
Erros comuns
Colocar o boundary dentro do componente que lança o erro. Um boundary só captura erros dos filhos. Se Profile renderiza <ErrorBoundary> em volta do próprio JSX e depois lança um erro no próprio corpo, o erro passa por ele até o próximo boundary acima. Envolva o componente a partir do pai.
Efeitos colaterais em getDerivedStateFromError. Ele executa durante a renderização e pode executar mais de uma vez, então limite-o a retornar estado. Logs ficam no componentDidCatch ou no onCaughtError da raiz.
Um reset que não corrige nada. Limpar o erro do boundary renderiza os mesmos filhos com as mesmas props. Se eles lançarem o erro de novo, o usuário volta para o fallback. Mude primeiro o que causou o erro (buscar de novo, limpar a entrada ruim, mudar a key) e depois limpe o erro, como o primeiro exemplo faz com onReset.
Um boundary para o app inteiro, e nada mais. Ele evita a página em branco, mas transforma toda falha pequena em um erro de página inteira. Adicione boundaries em volta das funcionalidades e mantenha o de nível superior como último recurso.
Fallbacks que escondem o erro de você. Uma mensagem amigável é o certo para os usuários, mas garanta que o erro ainda chegue aos seus logs. O React 19 registra erros capturados no console por padrão; em produção esse console é o do seu usuário, então envie os erros para um serviço a partir do componentDidCatch ou do onCaughtError.
Error boundaries combinam naturalmente com <Suspense>: o Suspense cuida do "ainda não está pronto", o boundary cuida do "falhou". Coloque o boundary fora do Suspense, como nos exemplos do use, para que um componente cubra carregamento, sucesso e falha.
Perguntas frequentes
O que é um error boundary no React?
Um componente que captura erros de JavaScript lançados durante a renderização de qualquer componente dentro dele e renderiza uma UI alternativa no lugar. Sem um, um erro durante a renderização tira o app inteiro da tela.
Existe um hook para error boundaries?
Não. Um error boundary precisa ser um componente de classe com static getDerivedStateFromError (e, se quiser, componentDidCatch). Você o escreve uma vez e o usa a partir de componentes de função como qualquer outro componente, ou instala o react-error-boundary, que envolve a classe para você.
Error boundaries capturam erros em event handlers?
Não. Event handlers executam fora da renderização, então o React não precisa de um boundary para se recuperar. Use try/catch no handler e, se quiser que o boundary apareça, guarde o erro no estado e lance-o durante a renderização.
Error boundaries capturam erros assíncronos?
Não os de setTimeout, de callbacks de promises ou de fetch().then() que você mesmo inicia. Eles capturam uma promise rejeitada lida com use e, no React 19, um erro lançado dentro de uma form action ou de uma função passada para o startTransition do useTransition.
Como reinicio um error boundary?
Limpe o estado de erro dele, normalmente a partir de um botão Try again no fallback, depois de corrigir o que causou o erro. Mudar a key do boundary também o reinicia, porque o React monta uma nova instância.