Why your Not Found UI is not rendering on NextJS 13

Why your Not Found UI is not rendering on NextJS 13

·

3 min read

If you're wondering why your NextJS 13 app is rendering the default 404 page and not the one you specified in your not-found.js file - keep reading.

The wrong way

Calling notFound() outside of your react component (in this case I called it in an async fetch function) will render the default 404 page instead.

// app/restaurant/[slug]/page.js

import { PrismaClient } from '@prisma/client'
import { notFound } from 'next/navigation'

// Instantiate a new Prisma client
const prisma = new PrismaClient()

// Define a function to fetch restaurants by slug using Prisma
export const fetchRestaurantsBySlug = async (slug) => {
  // Use Prisma to find a restaurant with the specified slug
  const restaurant = await prisma.restaurant.findUnique({
    where: {
      slug,
    }
  })

  // If the restaurant is not found, call notFound() from Next.js
  if (!restaurant) {
    notFound()
  }

  // Otherwise, return the found restaurant
  return restaurant
}

// Define a component to render restaurant details based on a slug parameter
export default async function RestaurantDetails({ params }) {
  const restaurant = await fetchRestaurantsBySlug(params.slug)

  return (
    <>
        { // Render the restaurant details UI here... }
    </>
  )
}

if you navigate to a not found page, you get the default 404 page from NextJS:

but what I wanted to see was my custom 404 page:

which renders from this file:

// app/restaurant/not-found.js

import Image from 'next/image'
import errorMascot from '../../public/icons/error.png'

export default function NotFound() {
  return (
    <div className='h-screen bg-gray-200 flex flex-col justify-center items-center gap-8'>
      <Image src={errorMascot} alt='error' className='w-56' />
      <div className='bg-white px-10 py-6 shadow rounded'>
        <h3 className='text-xl font-bold'>Well, this is embarrassing.</h3>
        <p className='mt-4'>We couldn't find that restaurant.</p>
        <p className='mt-4 text-xs'>Error code: 404</p>
      </div>
    </div>
  )
}

The correct way

Turns out, to render your custom Not Found UI from your not-found.js file, you have to call notFound() within the react component:

// app/restaurant/[slug]/page.jsx

// ...

// Define a function to fetch restaurants by slug using Prisma
export const fetchRestaurantsBySlug = async (slug) => {
  // Use Prisma to find a restaurant with the specified slug
  const restaurant = await prisma.restaurant.findUnique({
    where: {
      slug,
    }
  })

  // If the restaurant is not found, throw an error
  if (!restaurant) {
    throw new Error('Restaurant not found')
  }

  // Otherwise, return the found restaurant
  return restaurant
}

// Define a component to render restaurant details based on a slug parameter
export default async function RestaurantDetails({ params }) {
  let restaurant

  try {
    // Attempt to fetch the restaurant details based on the provided slug
    restaurant = await fetchRestaurantsBySlug(params.slug)
  } catch (error) {
    // If an error is caught, call the notFound() function provided by Next.js
    notFound()
  }

  return (
    <>
        { // Render the restaurant details UI here... }
    </>
  )
}

Hope this helps!

Resources

https://beta.nextjs.org/docs/api-reference/notfound

https://beta.nextjs.org/docs/api-reference/file-conventions/not-found

Did you find this article valuable?

Support dahlia by becoming a sponsor. Any amount is appreciated!