dahlia
everyday code then porrada

Follow

everyday code then porrada

Follow
Why your Not Found UI is not rendering on NextJS 13

Why your Not Found UI is not rendering on NextJS 13

dahlia's photo
dahlia
·Apr 2, 2023·

3 min read

Play this article

Table of contents

  • The wrong way
  • The correct way
  • Resources

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!

Learn more about Hashnode Sponsors
 
Share this