Next.js: Update documentation to better explain dynamic routing param availability

Created on 8 Jul 2019  ·  6Comments  ·  Source: vercel/next.js

Bug report

Describe the bug

Dynamic route params are not available during SSR or when exporting pages in combination with useRouter

To Reproduce

  1. Set up the dynamic routing example
  2. Add a console.log(id) statement to the /post/[id]/index.js page.
  3. The console output when navigating to /post/first by clicking a link is correctly first.
  4. However, when reloading http://localhost:3000/post/first, the console output will be undefined and _then_ first. Also the SSR'd source will be different from the client-side render.
  5. (The same behavior will show on statically exported pages)

Expected behavior

useRouter should also return the correct query when running server-side or during export.

It should still re-render statically exported pages including additional query params however!

System information

  • OS: macOS
  • Version of Next.js: 9.0.0
documentation needs investigation

Most helpful comment

@Timer I noticed that you closed this via #7831.

For the record: I still am a bit confused by the behavior here. Adding getInitialProps to a page seems to work and capturing the query parameters in getInitialProps also leads to the desired result.

_However_ the same effect can be achieved by just adding an _empty_ getInitialProps to a page. Just by its presence, useRouter will work as expected. E.g.

const Page: NextPage = () => {
  const router = useRouter(); // router.query will be populated during export

  return <div>Router locale is: {router.query.locale}</div>; 
};

Page.getInitialProps = async (ctx) => {
  return {}; // Does NOT need to read query from ctx
};

I find this implicit relationship between useRouter and getInitialProps quite odd and obscure, especially when the query is defined with exportPathMap 🤔

All 6 comments

Hey @herrstucki!

This the expected behavior because this page is not SSR'd -- since there's no getInitialProps it's always going to be prerendered, even without next export.

We'll update the documentation to better explain this.

@Timer thanks for the reply!

I see … but what’s confusing is that even when I use an explicit exportPathMap with predefined queries they still don’t get baked into the exported html. But I think they should?

Ah, I see what you're saying @herrstucki! We'll give this a closer look.

Just to clarify what I‘d expect:

  1. Page /post/[id]/index.js exported via exportPathMap with query: {id: 'foo'}
  2. router.query should be {id: 'foo'} during export render and in the html output
  3. When loading /post/foo/?a=b, the query should be {id: 'foo'} on initial render and {id: 'foo', a: 'b'} immediately in the second render after mount (that second part never worked in next 8 but does now in v9)

Thanks for this awesome release and all the hard work you put in! 👏

@Timer I noticed that you closed this via #7831.

For the record: I still am a bit confused by the behavior here. Adding getInitialProps to a page seems to work and capturing the query parameters in getInitialProps also leads to the desired result.

_However_ the same effect can be achieved by just adding an _empty_ getInitialProps to a page. Just by its presence, useRouter will work as expected. E.g.

const Page: NextPage = () => {
  const router = useRouter(); // router.query will be populated during export

  return <div>Router locale is: {router.query.locale}</div>; 
};

Page.getInitialProps = async (ctx) => {
  return {}; // Does NOT need to read query from ctx
};

I find this implicit relationship between useRouter and getInitialProps quite odd and obscure, especially when the query is defined with exportPathMap 🤔

Oh, I just saw #7829 … I assume that's going to resolve my previous comment?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

formula349 picture formula349  ·  3Comments

lixiaoyan picture lixiaoyan  ·  3Comments

jesselee34 picture jesselee34  ·  3Comments

YarivGilad picture YarivGilad  ·  3Comments

rauchg picture rauchg  ·  3Comments