2

I have a component inside a page in a dynamic route in Next.js that needs to read the URL query string parameters. The app has a collection of articles you can search, and you can get to a specific 'page' within the article by visiting the appropriate URL.

So I have a pages route like so in the file structure:

/pages -> /article -> /[articleId] -> [pageNum].tsx

[pageNum].tsx is SSR-enabled, i.e. it contains a getServerSideProps function.

When the user performs a search, the search parameters are kept in the query string i.e. ?q=something&order=date.... However, in the component in question if I do the following:

const router = useRouter();

useEffect(() => {
  if (!router.isReady) return;
  console.log(router.query);
}, [router]);

All I see in the console is the pathname parameters, and not the query string params. So if I visit:

.../123/456?q=something&order=date

The logged out query object is only ever:

{ articleId: 'something', pageNum: '456' }

This means that when we create a 'Back' button that retains the query string parameters, the URL we return to has unrecognised values in it and any applied filters are lost. Fundamentally I'm missing some valuable piece of information - why do the query string parameters not come through?

Logging out the router object outside a useEffect shows this:

asPath: "/article/article_100000/2?q=iceland"
back: ƒ ()
basePath: ""
beforePopState: ƒ ()
components: {/article/[articleId]/[pageNum]: {…}, /_app: {…}, /search/[start]/[size]: {…}}
defaultLocale: undefined
domainLocales: undefined
events: {on: ƒ, off: ƒ, emit: ƒ}
isFallback: false
isLocaleDomain: false
isPreview: false
isReady: true
locale: undefined
locales: undefined
pathname: "/article/[articleId]/[pageNum]"
prefetch: ƒ ()
push: ƒ ()
query:
  pageNum: "2"
  articleId: "article_100000"
[[Prototype]]: Object
reload: ƒ ()
replace: ƒ ()
route: "/article/[articleId]/[pageNum]"

It's possible to take the asPath property and shave bits off it to get what's needed but I don't understand why the query object doesn't have what I need.

mattlock
  • 121
  • 8

1 Answers1

3

Late for the reply but still -

router has a variable isReady which remains false when rendered from the server side, which is the first load. From the next load onwards it becomes true and starts providing query.

So to use this, we will have to apply useEffect

const router = useRouter();
React.useEffect(() => {
    if (router.isReady) {
        // Code using query
        console.log(router.query);
    }
}, [router.isReady]);
architjn
  • 1,397
  • 2
  • 13
  • 30