Bambou
Bambou

Reputation: 1077

How to do dynamic routes with Next.js and redirect to 404 if route is not found?

I'm currently trying to make a dynamic route with Next.js 13 with app folder, my request is that I want to define some static routes and if the slug does not match with what I put, it'll return a 404 page

Here is what I did with Next version at 13.0.5 and pages folder and this was working great, if I'm going to an unexisting page like /pages/post/foo, I'm redirected to 404 page

// pages/post/[id].tsx
import { useRouter } from "next/router";

const Post = () => {
  const router = useRouter();
  const { id, foo } = router.query;

  return (
    <div>
      <p>Post: {id}</p>
    </div>
  );
};

export const getStaticProps = () => ({
  props: {},
});

export const getStaticPaths = () => ({
  paths: [{ params: { id: "abc" } }, { params: { id: "abcd" } }],
  fallback: false,
});

export default Post;

Now I'm trying to do the same with app folder and this version of Next.js 13.4.4

// app/[locale]/post/[id].tsx
export const dynamicParams = false;
export const generateStaticParams = async () => [{ id: "abc" }, { id: "abcd" }];

const Post = ({ params: { id } }) => (
  <div>
    <p>Post: {id}</p>
  </div>
);

export default Post;

But the issue is that it's not working at all, I mean by that that the dynamic route is working but if I try something like /post/foo, it's not showing a 404 page I'm using next-intl for the locale change

A solution I thought was to do this

import { notFound } from "next/navigation";

const Post = ({ params: { id } }) => {
  if (!['abc', 'abcd'].includes(id)) notFound();

  return (/* ... */);
};

But I wanted to know if there was a better solution, thanks in advance!

Upvotes: 4

Views: 11458

Answers (3)

Ravi Vadher
Ravi Vadher

Reputation: 139

If you are using getStaticProps :

    export const getStaticPaths: GetStaticPaths = async ()=> {
        return {
            paths: [], //you can define your paths
            fallback: "blocking"
        }
    }

    export const getStaticProps: GetStaticProps = async (context) => {
       const slug = context.params?.slug as string;
       const posts = getTutorialBySlug(slug) ?? null;
    
       if (!posts) {
           return {
               notFound: true,
           };
       }
    
       return {
           props: {
               posts: posts,
           },
       };
    };

If you are using get ServerSideProps :

    export const getServerSideProps: GetServerSideProps = async (
      context
    ) => {
      const slug = context.params?.slug as string;
      const post = getPostBySlug(slug) ?? null;
    
      if (!post) {
        return {
          notFound: true, //redirects to 404 page
        };
      }
    
      return {
        props: {
          post,
        },
      };
    };

Upvotes: -2

Recur
Recur

Reputation: 116

https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config

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

You can use a combination of dynamic and dynamicParams to achieve this effect in combination with a not-found.tsx in the folder your route lives at.

// [id]/page.tsx

export default function IdPage({ id }: any) {
  return <>Something here...</>;
}

export async function generateStaticParams() {
  return ['1', '2', '3'].map((id) => ({
    id
  }));
}

export const dynamic = 'force-static';
export const dynamicParams = false;

Upvotes: 3

MHD
MHD

Reputation: 1360

To throw a "not found" page in Next.js using App Router for dynamic URLs, you would do this:

import { notFound } from 'next/navigation';

type Params = {
  id: string;
};

export default function YourPage({ params }: { params: Params }) {
  // quick for demo purposes
  if (params.id === '123') {
    notFound();
  }

  return (
    <p>Look at this page, this page is amazing!</p>
  );
}

See the official Next.js documentation here: https://nextjs.org/docs/app/api-reference/functions/not-found

Upvotes: 7

Related Questions