question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Use optional catch-all routes with getStaticPaths

See original GitHub issue

Bug report

Describe the bug

I’m trying to build dynamic nested SSG routes with Next. The goal is to be able to create any page using an external data source. I also want this method to cover the root (path /) page, so I’m using optional catch-all routes.

So after enabling experimental optional catch all routes in next.config.js, here is what I wrote:

In pages/[[...slug]].js :

const MyPage = ({ slug }) => {
  return <div>My page, slug {JSON.stringify(slug)}</div>;
};

export async function getStaticPaths() {
  const paths = [
    {
      params: { slug: [] },
    },
    {
      params: { slug: ["home"] },
    },
    {
      params: { slug: ["home", "page"] },
    },
  ];
  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  // Make sure params are what we expected
  console.log(params);
  return {
    props: {
      slug: params.slug,
    },
  };
}

export default MyPage;

When I try to access my routes (/, home and /home/page), I get a 404 instead. After running yarn build, I found out Next did this instead:

Page                                                           Size     First Load JS
┌   /_app                                                      3.47 kB        61.1 kB
├ ● /[[...slug]]                                               319 B          61.5 kB
├   ├ /[]
├   ├ /[home]
├   └ /[home/page]
└ ○ /404                                                       3.25 kB        64.4 kB

And in my logs, the values of params were:

  1. { slug: [ '[home', 'page]' ] }
  2. { slug: [ '[]' ] }
  3. { slug: [ '[home]' ] }

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Create a default Next app
  2. Create a next.config.js file with this content:
module.exports = {
  experimental: {
    optionalCatchAll: true,
  },
};
  1. In the pages folder, delete index.js and create a file called [[...slug]].js instead
  2. In that file, paste the code I included above
  3. Run yarn build
  4. See the result

Expected behavior

Next.js should have created these pages instead:

Page                                                           Size     First Load JS
┌   /_app                                                      3.47 kB        61.1 kB
├ ● /[[...slug]]                                               319 B          61.5 kB
├   ├ /
├   ├ /home
├   └ /home/page
└ ○ /404                                                       3.25 kB        64.4 kB

And I think the values of params in getStaticProps should have been:

  1. { slug: [ 'home', 'page' ] }
  2. { slug: [ ] }
  3. { slug: [ 'home' ] }

System information

  • OS: macOS 10.15.5

  • Version of Next.js: 9.4.4

  • Version of Node.js: 12.18.2

Additional context

My code fine with regular catch-all routes, with a file called [...slug].js and without the root page.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:4
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

3reactions
remidejcommented, Jul 6, 2020

So TLDR:

  • The bug does happen on Next 9.4.4 where optional catch-all routes are an experimental feature
  • It’s fixed in 9.4.5 (currently the canary release)
  • When there’s no slug, getStaticProps’ ctx.params is an empty object

Thanks for the help!

1reaction
Timercommented, Jul 6, 2020

This is the expected behavior. You’ll need to set a default value!

All falsy values passed into getStaticPaths result in the omission of the variable from params.

export async function getStaticProps({ params }) {
  // Make sure params are what we expected
  console.log(params);
  return {
    props: {
      slug: params.slug || null,
    },
  };
}

Or:

export async function getStaticProps({ params: { slug = null } }) {
  return {
    props: {
      slug
    },
  };
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Next.js catch all route not working as expected with ...
According to documentation, I want to navigate to t/a.cat and t/a.cat/a.id , but it only works for t/a.cat/a.id . export const getStaticPaths = ......
Read more >
Data Fetching: getStaticPaths - Next.js
Learn how to fetch data and generate static pages with `getStaticPaths`. ... If the page uses an optional catch-all route, use null ,...
Read more >
Noob question - Next 9.3+ and catch-all routes : r/nextjs - Reddit
Can anyone offer a Next.js noob any pointers on using getStaticPaths and getStaticProps with catch-all routes? Most Next.js 9.3+ blog ...
Read more >
Static Site Generation with Next.js and TypeScript (Part IV)
Optional catch-all routes match not only the catch-all routes that ... Note: The getStaticPaths() function can be used only when the page ...
Read more >
Static Page Generation using getStaticPaths in Next.js
If the page includes an optional catch-all route, render it null, [], undefined, or false. If you specify slug: false for pages/[[...slug]], ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found