Why your Not Found UI is not rendering on NextJS 13
Table of contents
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
Subscribe to my newsletter
Read articles from dahlia directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
dahlia
dahlia
A generalist specialised in marine predator foraging ecology. Currently learning solidity and how to become a better writer. Code by day, train jiu jitsu by night.