Capítulo 11 de 456
Divide erros em duas categorias com tratamento distinto: erros esperados (validação, request que falhou) modelados como valores de retorno, e exceções não capturadas (bugs) tratadas por error boundaries.
throw.useActionState: hook React usado com Server Functions para capturar o estado retornado (incluindo mensagem de erro) e refletir na UI.notFound(): função chamada dentro de um route segment para renderizar a UI de not-found.js (404) daquele segmento.error.js): arquivo de convenção que cria uma boundary de erro para um route segment; deve ser Client Component ('use client'); recebe error e retry.catchError: função (next/error) que cria error boundaries reutilizáveis para qualquer parte da árvore de componentes, não só no nível de rota.global-error.js: arquivo na raiz de app para tratar erros no root layout; precisa definir suas próprias tags <html> e <body> porque substitui o root layout quando ativo.try/catch manual + useState/useReducer.useTransition / startTransition: erros não tratados dentro de startTransition sobem até a error boundary mais próxima (exceção à regra acima).'use server'
export async function createPost(prevState: any, formData: FormData) {
const res = await fetch('https://api.vercel.app/posts', {
method: 'POST',
body: { title: formData.get('title'), content: formData.get('content') },
})
if (!res.ok) {
return { message: 'Failed to create post' }
}
}
throw.'use client'
import { useActionState } from 'react'
import { createPost } from '@/app/actions'
export function Form() {
const [state, formAction, pending] = useActionState(createPost, { message: '' })
return (
<form action={formAction}>
{state?.message && <p aria-live="polite">{state.message}</p>}
<button disabled={pending}>Create Post</button>
</form>
)
}
useActionState e exibir na UI.'use client'
import { useEffect } from 'react'
export default function ErrorPage({ error, retry }: { error: Error & { digest?: string }; retry: () => void }) {
useEffect(() => { console.error(error) }, [error])
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={() => retry()}>Try again</button>
</div>
)
}
app/dashboard/error.tsx como error boundary padrão de route segment, com log e recuperação via retry().'use client'
import { catchError, type ErrorInfo } from 'next/error'
function ErrorFallback(props: { title: string }, { error, retry }: ErrorInfo) {
return (
<div>
<h2>{props.title}</h2>
<p>{error.message}</p>
<button onClick={() => retry()}>Try again</button>
</div>
)
}
export default catchError(ErrorFallback)
catchError, reusável em qualquer ponto da árvore (não só rota inteira).try/catch + throw para erros esperados: dificulta exibir a mensagem na UI; modele como retorno de estado.try/catch e useState.'use client' em error.js/global-error.js: error boundaries precisam ser Client Components.useActionState; exceção não capturada = throw + error boundary.error.js cobre um route segment e propaga para o boundary pai mais próximo se não existir um local; global-error.js cobre o root layout inteiro e precisa de <html>/<body> próprios.catchError permite boundaries granulares em qualquer componente, não só por segmento de rota.startTransition sobem para a error boundary; erros em handlers de evento comuns não sobem, precisam de captura manual.notFound() + not-found.js é o padrão para 404 específico de um segmento (ex.: slug de post inexistente).