new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Next.js App Router · all subjects

error-handling

17 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Expected vs uncaught exceptions

Errors are divided into two categories: expected errors that occur during normal operation (such as form validation or failed requests) and should be handled explicitly and returned to the client, and uncaught exceptions that are unexpected bugs which should be caught by error boundaries.

useActionState hook for server function error handling

Use the useActionState hook from React to handle expected errors in Server Functions. Model expected errors as return values rather than using try/catch blocks. The hook returns [state, formAction, pending] where state contains the error information returned from the server function.

Server component error handling with conditional rendering

In Server Components, check the response status after fetching data and conditionally render an error message or use the redirect function if the request failed.

notFound function for 404 errors

Call the notFound function from 'next/navigation' within a route segment when a resource is not found. Pair it with a not-found.js file in the same segment to display a 404 UI.

error.js file creates error boundary

Create an error boundary by adding an error.js file inside a route segment and exporting a React component. Error boundaries must be Client Components (marked with 'use client'). The exported component receives error and retry props, where error is an Error object that may contain a digest property, and retry is a function to attempt recovery.

Error boundary component structure

An error boundary component receives error (Error & { digest?: string }) and retry (() => void) as props. It should use useEffect to log errors and can provide a retry button that calls the retry function to re-fetch and re-render the segment.

Error boundaries bubble up to nearest parent

Errors bubble up to the nearest parent error boundary. This allows for granular error handling by placing error.tsx files at different levels in the route hierarchy.

catchError function for component-level error recovery

Use the catchError function from 'next/error' to create error boundaries that wrap any part of your component tree. It takes a fallback component that receives props and an ErrorInfo object containing error and retry properties. Returns a wrapped component that can be used as a wrapper in layouts or pages.

Error boundaries don't catch event handler errors

Error boundaries are designed to catch errors during rendering, not in event handlers or async code. Errors in event handlers run after rendering and won't be caught by boundaries. Manually catch these errors and store them using useState or useReducer to update the UI.

Errors in useTransition bubble to error boundary

Unhandled errors inside startTransition from useTransition will bubble up to the nearest error boundary, unlike regular event handler errors which don't trigger boundaries.

global-error.js for root layout errors

Handle errors in the root layout using the global-error.js file located in the root app directory. Global error UI must be a Client Component and must define its own <html> and <body> tags, since it replaces the root layout or template when active.

Example: useActionState with server function error handling

Server function example showing expected error handling: ```ts 'use server' export async function createPost(prevState: any, formData: FormData) { const title = formData.get('title') const content = formData.get('content') const res = await fetch('https://api.vercel.app/posts', { method: 'POST', body: { title, content }, }) const json = await res.json() if (!res.ok) { return { message: 'Failed to create post' } } } ``` Client component using useActionState to display errors: ```tsx 'use client' import { useActionState } from 'react' import { createPost } from '@/app/actions' const initialState = { message: '', } export function Form() { const [state, formAction, pending] = useActionState(createPost, initialState) return ( <form action={formAction}> <label htmlFor="title">Title</label> <input type="text" id="title" name="title" required /> <label htmlFor="content">Content</label> <textarea id="content" name="content" required /> {state?.message && <p aria-live="polite">{state.message}</p>} <button disabled={pending}>Create Post</button> </form> ) } ```

Example: notFound function usage

Using notFound in a page component: ```tsx import { notFound } from 'next/navigation' import { getPostBySlug } from '@/lib/posts' export default async function Page({ params, }: { params: Promise<{ slug: string }> }) { const { slug } = await params const post = getPostBySlug(slug) if (!post) { notFound() } return <div>{post.title}</div> } ``` Corresponding not-found component: ```tsx export default function NotFound() { return <div>404 - Page Not Found</div> } ```

Example: error.js error boundary

Error boundary implementation: ```tsx 'use client' // Error boundaries must be Client Components import { useEffect } from 'react' export default function ErrorPage({ error, retry, }: { error: Error & { digest?: string } retry: () => void }) { useEffect(() => { // Log the error to an error reporting service console.error(error) }, [error]) return ( <div> <h2>Something went wrong!</h2> <button onClick={() => retry()} > Try again </button> </div> ) } ```

Example: catchError component-level error boundary

Creating a component-level error boundary with catchError: ```tsx '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) ``` Using the wrapped component: ```tsx import ErrorBoundary from './custom-error-boundary' export default function Component({ children }: { children: React.ReactNode }) { return <ErrorBoundary title="Dashboard Error">{children}</ErrorBoundary> } ```

Example: manual event handler error handling

Manually handling errors in event handlers using useState: ```tsx 'use client' import { useState } from 'react' export function Button() { const [error, setError] = useState(null) const handleClick = () => { try { // do some work that might fail throw new Error('Exception') } catch (reason) { setError(reason) } } if (error) { /* render fallback UI */ } return ( <button type="button" onClick={handleClick}> Click me </button> ) } ```

Example: global-error.js at root level

Global error handler for root layout: ```tsx 'use client' // Error boundaries must be Client Components export default function GlobalError({ error, retry, }: { error: Error & { digest?: string } retry: () => void }) { return ( // global-error must include html and body tags <html> <body> <h2>Something went wrong!</h2> <button onClick={() => retry()}>Try again</button> </body> </html> ) } ```

Give your agent this brain