How to Handle Error Pages and Custom Error Handling in Next.js
Create effective custom error pages and manage errors gracefully with Next.js's built-in features.
Introduction
Errors are inevitable in web applications. How you handle them can make or break your user experience. Next.js, being a versatile React framework, provides robust tools for handling errors effectively. Whether it’s a 404 page or a server-side error, Next.js simplifies error handling with custom error pages, client-side error boundaries, and detailed logging.
In this blog, we will explore:
Creating custom error pages in Next.js
Handling client-side and server-side errors
Best practices for error management
Main Content
1. Default Error Pages in Next.js
Next.js provides default error pages for common HTTP statuses like 404 and 500. These are functional but often lack branding or customization.
Default Pages:
404: Displayed when a page is not found.
500: Displayed for server-side errors.
Example: Visit a non-existent route, and Next.js will render its default 404 page automatically.
2. Creating a Custom 404 Page
A custom 404 page enhances user experience by aligning error messages with your app’s branding.
Steps to Create a Custom 404 Page:
Create a
404.js
file in thepages
directory.Add your custom content.
Code Example:
// pages/404.js
const Custom404 = () => {
return (
<div style={{ textAlign: 'center', padding: '50px' }}>
<h1>404 - Page Not Found</h1>
<p>The page you are looking for does not exist.</p>
</div>
);
};
export default Custom404;
Component Structure: A simple React component rendering custom content.
Styling: Inline styles for a clean layout.
3. Creating a Custom 500 Page
To create a custom server-side error page:
Create a
500.js
file in thepages
directory.Customize the page as desired.
Code Example:
// pages/500.js
const Custom500 = () => {
return (
<div style={{ textAlign: 'center', padding: '50px' }}>
<h1>500 - Internal Server Error</h1>
<p>Something went wrong on our end. Please try again later.</p>
</div>
);
};
export default Custom500;
Content: Displays a user-friendly message for server errors.
Custom Message: Adds branding and reassurance for users.
4. Handling Errors with getInitialProps
in _error.js
For more advanced error handling, you can use the _error.js
file. This allows capturing error details and rendering custom responses for various statuses.
Code Example:
// pages/_error.js
function Error({ statusCode }) {
return (
<div style={{ textAlign: 'center', padding: '50px' }}>
<h1>{statusCode ? `${statusCode} Error` : 'An error occurred'}</h1>
<p>{
statusCode
? `A ${statusCode} error occurred on the server.`
: 'An error occurred on the client.'
}</p>
</div>
);
}
Error.getInitialProps = ({ res, err }) => {
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
return { statusCode };
};
export default Error;
Dynamic Error Messages: Displays specific messages based on the status code.
getInitialProps
: Fetches server-side error details.
5. Implementing Client-Side Error Boundaries
React’s error boundaries catch JavaScript errors in components, preventing the entire app from crashing.
Steps to Add Error Boundaries:
Create an
ErrorBoundary
component.Wrap key components or pages with it.
Code Example:
// components/ErrorBoundary.js
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error('ErrorBoundary caught an error', error, info);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
getDerivedStateFromError
: Updates state when an error is detected.componentDidCatch
: Logs error details for debugging.
Usage:
import ErrorBoundary from '../components/ErrorBoundary';
function App() {
return (
<ErrorBoundary>
<YourComponent />
</ErrorBoundary>
);
}
- Wrap critical components to isolate errors.
6. Logging and Monitoring Errors
Logging errors is crucial for debugging and maintaining your application. Use services like Sentry or LogRocket to capture errors in production.
Example with Sentry:
Install Sentry:
npm install @sentry/nextjs
Configure Sentry in your app.
// sentry.server.config.js import * as Sentry from '@sentry/nextjs'; Sentry.init({ dsn: 'your-dsn', tracesSampleRate: 1.0, });
- DSN Configuration: Connects your app to Sentry’s monitoring service.
Examples/Case Studies
Case Study: E-Commerce Website
A large e-commerce site implemented custom 404 and 500 pages. This improved user retention during server outages and ensured users received helpful redirections when encountering broken links.
Case Study: SaaS Platform
A SaaS platform used error boundaries and Sentry for real-time error logging, reducing downtime and improving issue resolution by 30%.
Tips/Best Practices
User-Friendly Messages: Use simple, actionable language on error pages.
Styling: Maintain branding consistency in error pages.
Client-Side Errors: Use error boundaries for JavaScript issues.
Monitoring Tools: Integrate tools like Sentry for detailed error logs.
Test Thoroughly: Simulate various errors to ensure your handling is robust.
Conclusion
Error handling is an essential aspect of web development. With Next.js, creating custom error pages, implementing error boundaries, and using logging tools ensures a smooth user experience and robust application performance. By following best practices, you can turn errors into opportunities to reassure and guide users effectively.
Start enhancing your Next.js applications with custom error handling today! Explore the possibilities, test different strategies, and build reliable web applications.
References/Resources
*Image is designed by Freepik.