1

For example, I have a dynamic route /blog/[article-id].

When visiting an existing blog post /blog/id-that-exist, it works as expected, and now I want to handle the case /blog/id-that-does-not-exist properly.

The code in /blog/[id].jsx looks something like:

export const getStaticPaths async () => {
  return {
    fallback: true,
    paths: (await sequelize.models.Article.findAll()).map(
      article => {
        return {
          params: {
            pid: article.slug,
          }
        }
      }
    ),
  }
}

export const getStaticProps async () => {
  // Try to get it from the database. Returns none if does not exist.
  const article = await sequelize.models.Article.findOne({
    where: { slug: pid },
  });
  return { props: { article: article } };
}

const ArticlePage = (props) => {
  // This can happen due to fallback: true while waiting for
  // a page that was not rendered at build time to build.
  const router = useRouter()
  if (router.isFallback) {
    return <div>loading</div>;
  }
  return (
    <div>{props.article.body}</div>
  );
};

export const getStaticPaths = getStaticPathsArticle;
export const getStaticProps = getStaticPropsArticle;
export default ArticlePage;

I saw this related question: How to handle not found 404 for dynamic routes in Next.js which is calling API? but I'm not sure if it's the same as I'm asking here, as this does not depend on any external API being used.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985

2 Answers2

2

notFound: true from Next.js 10

Starting in Next.js 10, we can do:

export const getStaticProps async () => {
  // Try to get it from the database. Returns none if does not exist.
  const article = await sequelize.models.Article.findOne({
    where: { slug: pid },
  });
  if (!article) {
    return {
      notFound: true
    }
  }
  return { props: { article: article } };
}

as documented at: https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation

When notFound is returned, the rendering function ArticlePage just never gets called, and the default 404 page is returned instead.

Note however that ArticlePage did get

For some reason in development mode:

  • I don't get the expected 404 HTTP status code
  • ArticlePage, so if you forgot to handle the fallback case, the it might crash due to missing properties

which was confusing me a bit. But in production mode, everything works as expected.

Workaround before Next.js 10

As shown https://github.com/vercel/next.js/discussions/10960#discussioncomment-1201 you could previously do something like:

const ArticlePage = (props) => {
  if (!props.article) {
    return <>
      <Head>
        <meta name="robots" content="noindex">
      </Head>
      <DefaultErrorPage statusCode={404} />
    </>
  }
  return (
    <div>{props.article.body}</div>
  );
};

but this is not ideal because it does not set the HTTP return code correctly I believe, and I don't know how to do it.

Tested on Next.js 10.2.2.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
0

I've read your answer regarding the solution after Next.js v.10, but I didn't get what was the problem in showing the expected http 404 code during development.

I use Next.JS v.12 and I get the expected 404 normally in development

import { GetStaticPaths, GetStaticProps } from 'next'
import { useRouter } from 'next/router'
import { ParsedUrlQuery } from 'querystring'
import Loading from '../../components/loading'

export const getStaticPaths: GetStaticPaths = async () => {
   //your paths

    return { paths, fallback: true }
}

export const getStaticProps: GetStaticProps = async ({ params }: { params?: ParsedUrlQuery }) => {
   //get your props
if (!target){
return {notFound: true}
}

    return { props: { ... }, revalidate: 86400}
}

function Index({ ... }) {
    const router = useRouter()
    
    if (router.isFallback) {
        return <Loading />
    }
    return (
        <div>
           //my content
        </div>
    )
}

export default Index

When the target isn't found, it renders my custom 404 component in pages/404.tsx if I created one or just the default 404 page.

This should work normally during development and production.

MohamedZh
  • 189
  • 6