Part 69: Handling Non-Existent Pages Gracefully in Next.js

[App] Dynamic Rendering and Revalidation

Dynamic Rendering and Revalidation

As we continue to build our Next.js application, ensuring that it handles non-existent content gracefully is a key aspect of providing a robust user experience. In this blog post, we'll explore how to manage 404 errors effectively, especially when using dynamic content fetching with Next.js.

The Need for Dynamic Rendering

In our application, we've been using the force-dynamic setting to ensure that pages fetch the latest data from our CMS each time they are requested. This approach is beneficial for displaying real-time updates, but it also raises a question: what happens if a user requests a page that doesn't exist, such as a review with an invalid slug?

The Problem with Invalid Slugs

When a user requests a non-existent page like /reviews/xyz, the application currently throws an error. This happens because our ReviewPage component attempts to fetch data for the non-existent slug, resulting in an "undefined" item. The error arises when the code tries to access properties of this undefined object.

Handling Non-Existent Content

To handle this scenario, we need to adjust our data-fetching logic to account for cases where the requested data doesn't exist. Here's how we can do that:

  1. Check for Empty Data: In the getReview function, we need to check if the data array returned by the CMS is empty. If it is, we should return null to indicate that the review doesn't exist.

    // lib/reviews.js
    export async function getReview(slug) {
      const { data } = await fetchReviews({
        filters: { slug: { $eq: slug } },
        fields: ['slug', 'title', 'subtitle', 'publishedAt', 'body'],
        populate: { image: { fields: ['url'] } },
        pagination: { pageSize: 1, withCount: false },
      });
      if (data.length === 0) {
        return null;
      }
      const item = data[0];
      return {
        ...toReview(item),
        body: marked(item.attributes.body,{headerIds: false, mangle: false}),
      };
    }
  2. Use the notFound Function: Next.js provides a convenient notFound function from the next/navigation module. This function stops the normal rendering process and returns a 404 page if the requested content doesn't exist.

    // app/reviews/[slug]/page.jsx
    import { notFound } from 'next/navigation';
    
    export async function generateMetadata({ params: { slug } }) {
      const review = await getReview(slug);
      if (!review) {
        notFound();
      }
      return {
        title: review.title,
      };
    }
    
    export default async function ReviewPage({ params: { slug } }) {
      const review = await getReview(slug);
      if (!review) {
        notFound();
      }
    
      return (
        <>
          <Heading>{review.title}</Heading>
          <p className="pb-2">{review.subtitle}</p>
          <div className="flex gap-3 items-baseline">
            <p className="italic pb-2">{review.date}</p>
            <ShareLinkButton />
          </div>
          <Image src={review.image} alt={review.title} priority width="640" height="360" className="mb-2 rounded" />
          <article dangerouslySetInnerHTML={{ __html: review.body }} className="prose prose-slate max-w-screen-sm" />
        </>
      );
    }
  3. Customize the 404 Page: We can customize the 404 page by creating a not-found.jsx file in the app directory. This special file will be used for all 404 responses, allowing us to provide a unique message or design.

    // app/not-found.jsx
    import Heading from '@/components/Heading';
    
    export default function NotFoundPage() {
      return (
        <>
          <Heading>Not Found</Heading>
          <p>
            Oops, the page you requested only exists in a parallel universe.
          </p>
        </>
      );
    }

Testing the Solution

After implementing these changes, try accessing a non-existent review slug like /reviews/xyz. You should now see your custom 404 page instead of an error. This approach ensures that your application handles invalid routes gracefully, maintaining a smooth user experience.

Conclusion

By incorporating error handling for non-existent content, we've made our Next.js application more robust and user-friendly. Using the notFound function and customizing the 404 page are simple yet effective strategies to improve error management in your application. As you continue developing your project, consider other edge cases where similar error handling might be beneficial. This attention to detail will contribute to a polished and professional end product.

Last updated