Carregamento e Tratamento de Erros
Arquivos especiais loading.tsx, error.tsx e not-found.tsx criam limites automáticos de Suspense e Error Boundaries com escopo para segmentos de rota.
Busque em todas as páginas da documentação
Arquivos especiais loading.tsx, error.tsx e not-found.tsx criam limites automáticos de Suspense e Error Boundaries com escopo para segmentos de rota.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Cartão de receita de referência rápida - pronto para copiar e colar.
app/
├── loading.tsx # Fallback global de carregamento
├── error.tsx # Error boundary global
├── not-found.tsx # 404 global
└── dashboard/
├── loading.tsx # Fallback de carregamento para /dashboard
├── error.tsx # Error boundary para /dashboard
└── page.tsx
// app/dashboard/loading.tsx
export default function Loading() {
return <div className="animate-pulse">Carregando dashboard...</div>;
}
// app/dashboard/error.tsx
"use client";
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
return (
<div>
<h2>Algo deu errado</h2>
<button onClick={reset}>Tentar novamente</button>
</div>
);
}Quando usar isso: Todo segmento de rota que busca dados deve ter um loading.tsx. Todo segmento onde os erros são recuperáveis deve ter um error.tsx.
// app/dashboard/loading.tsx - Estado de carregamento esquelético
export default function DashboardLoading() {
return (
<div className="space-y-4 p-6">
<div className="h-8 w-48 animate-pulse rounded bg-gray-200" />
<div className="grid grid-cols-3 gap-4">
{Array.from({ length: 3 }).map((_, i) => (
<div key={i} className="h-32 animate-pulse rounded-lg bg-gray-200" />
))}
</div>
<div className="h-64 animate-pulse rounded-lg bg-gray-200" />
</div>
);
}// app/dashboard/error.tsx - Deve ser um Componente Cliente
"use client";
import { useEffect } from "react";
export default function DashboardError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// Registrar erro no serviço de monitoramento
console.error("Erro no Dashboard:", error);
}, [error]);
return (
<div className="flex flex-col items-center justify-center p-12">
<h2 className="text-xl font-bold text-red-600">Erro no Dashboard</h2>
<p className="mt-2 text-gray-600">
{error.message || "Ocorreu um erro inesperado."}
</p>
{error.digest && (
<p className="mt-1 text-sm text-gray-400">ID do Erro: {error.digest}</p>
)}
<button
onClick={reset}
className="mt-4 rounded bg-blue-600 px-4 py-2 text-white hover:bg-blue-700"
>
Tentar Novamente
</button>
</div>
);
}// app/dashboard/page.tsx - Componente Servidor que pode falhar
import { notFound } from "next/navigation";
async function getDashboardData() {
const res = await fetch("https://api.example.com/dashboard", {
next: { revalidate: 60 },
});
if (res.status === 404) notFound();
if (!res.ok) throw new Error("Falha ao carregar dados do dashboard");
return res.json();
}
export default async function DashboardPage() {
const data = await getDashboardData();
return (
<div className="p-6">
<h1 className="text-2xl font-bold">Dashboard</h1>
<div className="mt-4 grid grid-cols-3 gap-4">
<StatCard label="Receita" value={data.revenue} />
<StatCard label="Usuários" value={data.users} />
<StatCard label="Pedidos" value={data.orders} />
</div>
</div>
);
}
function StatCard({ label, value }: { label: string; value: number }) {
return (
<div className="rounded-lg border p-4">
<p className="text-sm text-gray-500">{label}</p>
<p className="text-2xl font-bold">{value.toLocaleString()}</p>
</div>
);
}// app/not-found.tsx - Página 404 personalizada
import Link from "next/link";
export default function NotFound() {
return (
<div className="flex min-h-screen flex-col items-center justify-center">
<h1 className="text-6xl font-bold">404</h1>
<p className="mt-4 text-xl text-gray-600">Página não encontrada</p>
<Link
href="/"
className="mt-6 rounded bg-blue-600 px-6 py-2 text-white hover:bg-blue-700"
>
Ir para Início
</Link>
</div>
);
}loading.tsx envolve a página em um limite <Suspense>. O Next.js gera automaticamente <Suspense fallback={<Loading />}><Page /></Suspense>. A UI de carregamento aparece instantaneamente enquanto a página é transmitida.error.tsx envolve a página em um Error Boundary do React. Ele captura erros de JavaScript na página e seus filhos durante a renderização. A função reset re-renderiza o conteúdo do error boundary.error.tsx deve ser um Componente Cliente. Error Boundaries são um recurso do React do lado do cliente. Sempre adicione "use client" no topo.error.tsx não captura erros no layout.tsx do mesmo nível. O error boundary fica entre o layout e a página. Para capturar erros de layout, coloque error.tsx no segmento pai.not-found.tsx é acionado por chamadas notFound() ou rotas não correspondentes. O not-found.tsx raiz é o fallback para todas as URLs não correspondentes. O not-found.tsx aninhado só é ativado quando você chama explicitamente notFound().loading.tsx. O layout é renderizado imediatamente, o fallback de carregamento é exibido e o conteúdo da página é transmitido quando pronto.// Carregamento aninhado - apenas o segmento mais interno mostra o carregamento
// app/dashboard/settings/loading.tsx
export default function SettingsLoading() {
return <p>Carregando configurações...</p>;
// O layout do dashboard e a barra lateral permanecem visíveis
}// Error boundary global - captura erros em todo o aplicativo
// app/global-error.tsx
"use client";
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<html>
<body>
<h1>Algo deu muito errado</h1>
<button onClick={reset}>Tentar novamente</button>
</body>
</html>
);
}
// Nota: global-error.tsx substitui o layout raiz, portanto, deve incluir <html> e <body>// Limites Suspense manuais para estados de carregamento granulares
// app/dashboard/page.tsx
import { Suspense } from "react";
export default function DashboardPage() {
return (
<div className="grid grid-cols-2 gap-4">
<Suspense fallback={<Skeleton />}>
<RevenueChart />
</Suspense>
<Suspense fallback={<Skeleton />}>
<UserTable />
</Suspense>
</div>
);
}
async function RevenueChart() {
const data = await getRevenue(); // transmite independentemente
return <div>{/* gráfico */}</div>;
}
async function UserTable() {
const users = await getUsers(); // transmite independentemente
return <table>{/* linhas */}</table>;
}
function Skeleton() {
return <div className="h-48 animate-pulse rounded bg-gray-200" />;
}// Tipo das props de error.tsx
interface ErrorProps {
error: Error & { digest?: string }; // digest é um hash de erro do lado do servidor
reset: () => void; // re-renderiza o error boundary
}
// loading.tsx e not-found.tsx não recebem props
// São componentes simples sem parâmetros
// global-error.tsx tem as mesmas props de error.tsx
// mas deve renderizar seu próprio <html> e <body>error.tsx deve ter "use client". Esquecer isso causa um erro de compilação. Error Boundaries são inerentemente do lado do cliente.error.tsx não pode capturar erros em seu layout.tsx irmão. O limite envolve a página, não o layout. Use um error.tsx pai para capturar erros de layout.global-error.tsx só ativa em produção. Em desenvolvimento, a sobreposição de erros do Next.js aparece em vez disso.global-error.tsx deve incluir <html> e <body>. Ele substitui totalmente o layout raiz quando acionado.notFound() de next/navigation lança um erro. O código após notFound() é inalcançável. O TypeScript pode não avisar sobre isso.loading.tsx é exibido na carga inicial e em navegações subsequentes. Ele aparece toda vez que o componente da página do segmento está pendente.reset() só funciona para erros do lado do cliente. Se um Componente Servidor lançar um erro, reset() tentará renderizar novamente, mas o mesmo erro do servidor pode ocorrer novamente sem uma correção de código ou alteração de dados.| Abordagem | Quando Usar |
|---|---|
Limite <Suspense> manual | Estados de carregamento granulares dentro de uma única página |
Biblioteca Error Boundary do React | Tratamento de erros personalizado em Componentes Cliente |
try/catch em Componentes Servidor | Tratamento de erros sem exibir o error boundary |
| Redirecionamento em caso de erro | Enviar usuários para uma página diferente em vez de exibir uma UI de erro |
unstable_rethrow | Relançar erros internos do Next.js (redirecionamentos, notFound) de blocos catch |
Error Boundaries são um recurso do React do lado do cliente. Eles dependem dos métodos de ciclo de vida componentDidCatch, que só existem no cliente. Você deve adicionar "use client" no topo de cada arquivo error.tsx.
Não. O error boundary envolve a página, não o layout no mesmo nível. Para capturar erros de layout, coloque error.tsx no segmento pai.
error.tsx captura erros dentro de um segmento de rota específicoglobal-error.tsx captura erros em todo o aplicativo, incluindo erros do layout raizglobal-error.tsx deve incluir seu próprio <html> e <body> porque substitui o layout raizglobal-error.tsx só ativa em produção; em desenvolvimento, a sobreposição de erros do Next.js aparece em vez dissoO Next.js gera <Suspense fallback={<Loading />}><Page /></Suspense> internamente. A UI de carregamento renderiza instantaneamente enquanto o conteúdo da página é transmitido.
Ele é exibido na carga inicial e em cada navegação subsequente para esse segmento. Sempre que o componente da página está pendente, o fallback de carregamento aparece.
not-found.tsx raiz é acionado automaticamente para todas as URLs não correspondentesnot-found.tsx aninhado só é ativado quando você chama explicitamente notFound() de next/navigationEla re-renderiza o conteúdo do error boundary, tentando renderizar a página novamente. Para erros do lado do cliente, isso tenta a renderização novamente. Para erros do servidor, o mesmo erro pode ocorrer novamente sem uma alteração de dados ou código.
import { Suspense } from "react";
export default function Page() {
return (
<div className="grid grid-cols-2 gap-4">
<Suspense fallback={<Skeleton />}>
<RevenueChart />
</Suspense>
<Suspense fallback={<Skeleton />}>
<UserTable />
</Suspense>
</div>
);
}Cada componente assíncrono é transmitido independentemente.
interface ErrorProps {
error: Error & { digest?: string };
reset: () => void;
}A propriedade digest é um hash de erro do lado do servidor útil para registro.
notFound() lança um erro internamente, então o bloco catch o interceptará. Use unstable_rethrow em blocos catch para relançar erros internos do Next.js como notFound() e redirect().
Não. Ambos são componentes simples sem parâmetros. Eles não recebem props do Next.js.
loading.tsx de cada segmento mostra um fallback para sua parte da páginanotFound() e redirect()Revisado por Chris St. John·Última atualização: 10 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥