Not-found page does not work in next.js 13
Asked Answered
A

7

23

This is the sturcure of my next.js project.

enter image description here

And my 404.js page is :

'use client';

export default function NotFound() {
    return (
        <div>
            <h2>Not Found</h2>
        </div>
    );
}

when I enter the wrong route it does not work and does not go to my custom page and goes to next.js 404 page. why, Where am I wrong?

thanks in advance.

Alyssaalyssum answered 31/1, 2023 at 19:41 Comment(1)
Hello and welcome to Stack Overflow. Please read Why should I not upload images of code/data/errors? to see how you can improve your question.Leslee
L
65

With Next 13.3 you just need to change the file name to not-found.js.

An app/not-found.js file will now automatically handle visits to an URL that does not have a matching route in your app.

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

Announced in : https://nextjs.org/blog/next-13-3


With Next 13.2, according to the docs:

"Note: not-found.js currently only renders when triggered by the notFound function, we're working on support for catching unmatched routes."

So it's not yet automatic but looks like they are working on it. File should also be named not-found.js instead of 404.js,

In the meantime, as it looks like dynamic routes are resolved after static routes, you can solve it by creating a dynamic catch-all route using a [...not_found] folder and add it to your app folder.

Image of folder structure for a Next 13 application showing the app folder with a [...not_found] folder, an articles folder and a layout.js, not-found.js, and page.js file in the root of the app folder.

Inside the dynamic route folder add a page.js file that calls the notFound() function.

app/[...not_found]/page.js

import {notFound} from "next/navigation"

export default function NotFoundCatchAll() {
  notFound()
}

And inside the not-found.js file in the root of your app folder you can add your custom 404 page.

app/not-found.js

import Link from 'next/link'

export default function NotFound() {
  return <div>
      <h1>Not found – 404!</h1>
      <div>
        <Link href="/">Go back to Home</Link>
      </div>
  </div>
}

Important to note that this approach can create problems if you have multiple dynamic routes in your app folder. Dynamic routes in another static folder should be fine however.

Hope it helps and good luck!

Lolly answered 3/3, 2023 at 9:12 Comment(6)
Please read Why should I not upload images of code/data/errors? to see how you can improve your answer.Leslee
Is it possible to explicitly navigate to the src/app/not-found.js? Like by going to app.com/not-found? What I'm trying to do is use the custom server and specifically render the not-found page. The render404 doesn't appear to work.Conjugated
I have this setup correctly, yet my 404 template is missing all styles. The Layout template is being inherited, but all of my styles are missing. Any thoughts on how to diagnose this?Cassimere
This seems to be still needed in nextjs 14, if anyone is wondering. Also in my case, the "catch all" did not work to redirect me to any not-found.js.Anastigmat
Same here, in NextJS 14 the "catch all" does not redirect to the root not-found.tsx.Maccaboy
@Maccaboy @Anastigmat Assuming you migrated from a SPA with react-router-dom and wrapped it into a [[...slug]] catch all, the reason is that nextjs will let react-router handle the redirects for all other routes that are not defined by the folder route system. in this case i used import { notFound } from 'next/navigation'and notFound()instead of the <Redirect to={appRoutes.notFound} />where in the old react-router code i handled the error redirects to hand it over to nextjs againTerbium
S
6

NextJS13 doesnt do error handling in this format, you dont want to use a file named 404.js but instead a file named error.js.

This will catch any errors sent from an API request returning a 404 response.

Docs here: https://beta.nextjs.org/docs/routing/error-handling


If your API instead returns a 200 response but an empty body, you could create another component named not-found.js, import that into the file you want it to show on, and return it on if the api is empty, for example:

app/dashboard/not-found.js

export default function NotFound() {
  return (
    <>
      <h2>Not Found</h2>
      <p>Could not find requested resource</p>
    </>
  );
}

app/dashboard/index.js:

import { notFound } from 'next/navigation';

async function fetchUsers(id) {
  const res = await fetch('https://...');
  if (!res.ok) return undefined;
  return res.json();
}

export default async function Profile({ params }) {
  const user = await fetchUser(params.id);

  if (!user) {
    notFound();
  }

  // ...
}

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

Summers answered 2/2, 2023 at 11:24 Comment(1)
Is it possible to explicitly navigate to the src/app/not-found.js? Like by going to app.com/not-found? What I'm trying to do is use the custom server and specifically render the not-found page. The render404 doesn't appear to work.Conjugated
T
2

As @Fredrik Carlsson said

With Next 13.3 you just need to change the file name to not-found.js

While this applies to 13.3 and up, I still couldn't get it to work. Instead, I kept getting this issue:

Uncaught (in promise) Error: NEXT_NOT_FOUND at notFound

Turns out that the issue is due to me using 'use client' at the top of my file. After removing that line, my not-found.js file works correctly.

If you're curious about structure and how I'm specifying my not-found file, I've got:

  • One file in /app/not-found.js which handles any invalid routes in root /
  • And another in /app/blog/[slug]/not-found.js which handles any invalid routes in blog /blog

If you're curious about how I'm triggering the not-found function:

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

async function getBlogPost(slug) {
  const blogPost = await client.fetch('https://example.com/...')

  if (!blogPost) {
    notFound() // <-- this triggers this the nearest not-found.js file
  }
  return blogPost
}

const BlogPost = async ({params}) => {
  const slug = params.slug
  const post = await getBlogPost(slug)

  return <Post post={post} />
}

export default BlogPost

References

Thaumaturge answered 3/10, 2023 at 16:43 Comment(0)
G
2

Create a directory labeled [404], and within it, place the page.{tsx/jsx/js} file as usual. You're all set!

Guthrun answered 23/10, 2023 at 5:29 Comment(1)
This is actually a reasonable option. If you want to return the proper HTTP code 404, you could create [404].page.ts with this content: ``` import { notFound } from "next/navigation"; export default function Page() { notFound(); } ``` And then create a not-found.tsx in the same directory.Revulsive
H
0

For video reference in codeGrepper => https://www.grepper.com/answers/723464/Not-found+page+does+not+work+in+next.js+13?ucard=1

//src\app\not-found.tsx

export default function NotFound() {
  return (
    <div>
      <h2>Page not found</h2>
      <p>Are you lost?</p>
    </div>
  );
}

for overall website you can use not-found.tsx or jsx in root of app folder

app\products[productId]\reviews[reviewId]\page.tsx

for seperate dynamic not found page use notFound function from next/navigation we can also create seperate 404 page for each route segment making seperate not-found.tsx here below we display that

import { notFound } from "next/navigation";

export default function ReviewDetail({
  params,
}: {
  params: { productId: string; reviewId: string };
}) {
  if (parseInt(params.reviewId) > 1000) {
    notFound();
  }  

  return (
    <h1>
      Review {params.reviewId} for product {params.productId}{" "}
    </h1>
  );
}

//src\app\products[productId]\reviews[reviewId]\not-found.tsx

export default function NotFound() {
  return (
    <div>
      <h2>Review not found cannot be greater then 1000 id</h2>
    </div>
  );       
}
Hygienist answered 24/11, 2023 at 6:20 Comment(0)
G
0

change file name to not-found.js or if you're using type script change file name to not-found.tsx.

Gallard answered 4/12, 2023 at 6:36 Comment(0)
G
-9

To create a not-found page in Next.js using the app folder, you can follow these steps:

  1. Create a new folder named pages in your project's root directory.

  2. In the pages folder, create a new file named 404.js.

  3. In the 404.js file, add the following code to render the Not Found page:

    const NotFound = () => {
      return (
        <div>
          <h1>404 - Not Found</h1>
        </div>
      )
    }
    
    export default NotFound
    
  4. In your _app.js file, add a catch-all route to display the Not Found page for any unknown routes:

import App, { Container } from 'next/app'

class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }

    return { pageProps }
  }

  render() {
    const { Component, pageProps } = this.props

    return (
      <Container>
        <Component {...pageProps} />
      </Container>
    )
  }
}

export default MyApp

Now, when a user visits a route that does not exist in your application, the Not Found page will be displayed.

Gaze answered 2/2, 2023 at 5:24 Comment(1)
This is a great answer for nextjs 12 and below. The user wants NextJS13 which uses the new React Server Components in the new /app folder and not the /pages folder.Summers

© 2022 - 2024 — McMap. All rights reserved.