Handling Frontend Errors in Next.js 13 App Router: A Brief Guide
--
You know when you get stuck with Next 13. You try to find the solution on Google. It turns out it’s completely jibberish.
As with many things Next introduced new ways of error handling along with changes to everything else.
If you’ve recently migrated or started using this router, you might find yourself a tad perplexed when trying to tackle front-end errors. This post will guide you through it.
1. The Basics: Using Error Boundaries with Next.js
React developers are familiar with error boundaries, a robust mechanism to catch and handle unexpected errors in components gracefully. Next.js has now embedded this feature but with its unique touch.
To utilize an error boundary in Next.js, create an error.tsx
right next to your page.tsx
. This special error page will be triggered when a client error happens.
For instance, for the page app/login/page.tsx
, you can create the following file:
// app/login/error.tsx'use client'export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</div>
);
}
The system will render this component if an uncaught error arises within app/login/page.tsx
. You can create an error.tsx
for any nested page, offering flexibility in error handling across different parts of your application.
2. Important Notes: Tricky Situations with Layouts
If you have a layout.tsx
alongside your page.tsx
, do note that errors originating from the layout won't be caught by the same level error.tsx
. This happens because the error boundary gets rendered beneath the layout.
I learned this the hard way when an error from a getUser
function in layout.tsx
bypassed the error handler. To catch such overarching issues, Next.js provides a app/global-error.tsx
.
Think of this global error boundary as similar to the following React structure.
How it’s done in regular React
function App() {
return (
<ErrorBoundary FallbackComponent={ErrorFallback} onError={logErrorToService}>
<MyComponent />
</ErrorBoundary>
);
}
How Next is doing it:
// app/global-error.tsx
'use client'
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<html>
<body>
<h2>This is a major disaster!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
)
}
This ensures that no matter where the error springs from, it won’t slip through unnoticed.
3. A Note on Security
For server-rendered components, Next.js ensures security by omitting sensitive details from console logs in production. However, be cautious: these details are visible in development mode.
Wrap Up
Error handling is crucial for any application’s stability and user experience. With Next.js 13’s new App Router, while the process might seem a bit intricate initially, it offers an organized and robust mechanism to catch and manage these discrepancies.
Stay tuned for my next post, where I’ll discuss handling errors on the backend of Next 13, complete with integrating proper logging using Google Cloud Logging.
Further Reading: