Next.js: Shallow routing for dynamic routes

Created on 25 Jul 2019  路  18Comments  路  Source: vercel/next.js

Hi. Is there a way with next.js v9 to navigate from /post/123 to /post/124 shallowly?
Here's my page structure:

  post
    [id]

Tried

const href = `/post/124`
const as = href
Router.push(href, as, {shallow: true})

when I'm on /post/123 page with no luck (the page refreshes).

What I need to achieve - I have a sidebar with posts list on the left of the page and selected post on the right. So when clicking a post title in sidebar I show it on the right and I also need to update the url, without refreshing the page.

Most helpful comment

Oh my god, I was understanding [postId] as a macro to be replaced by me when coding but, in fact, It is [postId] literally what have to be wroten. Now that I've understood that it works like a charm.

Sorry and thank you very much @Timer @timneutkens for your patience. :-)

For future stupids, like me, what have to be replaced during your program execution is the as part but not the href (that is a literal string declaring your filesystem path):

            Your code shouldn't
                 change this
              during execution
                     |
                     v
<Link href="/post/[postId]" as={`/post/${id}`}>
  <a>First Post</a>                      ^
</Link>                                  |
                                  This is what you
                             have to modify dynamically
                                during the execution

All 18 comments

I'm experiencing the same issue but using <Link href="/posts/whatever">. It seems dynamic routes are forcing SSR and there's no way to avoid that.

If I go from /posts/whatever to /posts everything works as expected, but when I go from /posts to /posts/whatever then SSR is forced.

As per my tests, it does not depends on the execution mode (development vs. production). It is happening in all cases.

href is the path inside the pages directory
as is the url in the browser

See docs here: https://nextjs.org/docs#dynamic-routes

@timneutkens sorry but I don't understand your answer... Keeping in mind I've of course read the documentation carefully, maybe I'm missing something.

In case you don't want to show a different URL than the real path in the pages directory, it is ok to set the same value in as and href, right? It is what @yantakus is doing.

I've also tried to set only href and not as but the behavior is exactly the same: SSR with full page refresh.

@timneutkens thanks, it worked. There's nothing about it in https://nextjs.org/docs#shallow-routing chapter of the docs. That's why I was confused.

@sgmonda, the linked documentation states that a <Link> component looks like this:

<Link href="/post/[postId]" as="/post/first-post">
  <a>First Post</a>
</Link>

Your provided example mismatches this <Link href="/posts/whatever">.

@Timer I've also tried setting <Link href="/post/[postId]" as="/post/[postId]"/> (as I don't need a different URL than the real path) but the same behavior is observed. A client-side page change is expected but a SSR happens, with a full page refresh.

Maybe I'm missing something. I'm making more tests in order to being able to provide more info or a simple running example.

That, too, does not match the provided example @sgmonda. Please use the values exactly as displayed above.

Oh my god, I was understanding [postId] as a macro to be replaced by me when coding but, in fact, It is [postId] literally what have to be wroten. Now that I've understood that it works like a charm.

Sorry and thank you very much @Timer @timneutkens for your patience. :-)

For future stupids, like me, what have to be replaced during your program execution is the as part but not the href (that is a literal string declaring your filesystem path):

            Your code shouldn't
                 change this
              during execution
                     |
                     v
<Link href="/post/[postId]" as={`/post/${id}`}>
  <a>First Post</a>                      ^
</Link>                                  |
                                  This is what you
                             have to modify dynamically
                                during the execution

@sgmonda maybe you could PR our documentation clarifying this for other users? In all relevant sections.

It doesn't work for me!

my directory:

    [category]
        [table]
Router.push(
      '/test/[category]/[table]' ,
      '/test/somecat/sometable',
      { shallow: true },
    );

It doesn't work for me!

my directory:

    [category]
        [table]
Router.push(
      '/test/[category]/[table]' ,
      '/test/somecat/sometable',
      { shallow: true },
    );

you are moving to [table] from [category] so shallow is ignored because you are going to other file. I have the same problem. If I use shallow it means I don't want to change rout (for example I am opening modal). I just need to change url in browser and if I link it to someone I will handle it in other file for SSR.

@timneutkens

Oh my god, I was understanding [postId] as a macro to be replaced by me when coding but, in fact, It is [postId] literally what have to be wroten. Now that I've understood that it works like a charm.

Sorry and thank you very much @Timer @timneutkens for your patience. :-)

For future stupids, like me, what have to be replaced during your program execution is the as part but not the href (that is a literal string declaring your filesystem path):

            Your code shouldn't
                 change this
              during execution
                     |
                     v
<Link href="/post/[postId]" as={`/post/${id}`}>
  <a>First Post</a>                      ^
</Link>                                  |
                                  This is what you
                             have to modify dynamically
                                during the execution

Man !!!!! You just saved my life, I have literally spent 2 hours going crazy.... I put the href as /something/[somethingElse] and now it works.

https://nextjs.org/docs/routing/shallow-routing
this code leads to adding parameters to the string instead of replacing, it turns out ?params=1?params=2?params=3

There is still an unanswered question around dynamic routing and shallow routing.

Say we start on the following page

// URL = /post/2020/01/01/hello-world
// Page = /post/[...slug].js
router.push(
  '/post/[...slug]',
  '/post/2020/01/01/hello-world',
  { shallow: true }
);

Then we route to another blog post:

// URL = /post/2020/01/01/foo-bar
// Page = /post/[...slug].js
router.push(
  '/post/[...slug]',
  '/post/2020/01/01/foo-bar',
  { shallow: true }
);

This does not trigger shallow routing, the browser refreshes, why?

I just ran into this same issue and found this post, as well as the added docs by @sgmonda useful. That being said, I'm curious if removing it from the documentation was intentional or if it was moved somewhere else? I see it in the old docs but see no mention of it in the new docs

Thanks @sgmonda for making that clear.

I know this is kind of unrelated but it's in the same ballpark, is there a way of updating the route with a SEO freindly URL?

IE:

        <Link href="/category/[pid]" as="/category/123" seoFriendly="/some-category">
            <a>Some Category</a>
        </Link>

In case someone needs to add a query in the current dynamic route e.g.: /password/reset/5f3ae750dcd8250da0d5c1f0

router.push(`/password/reset/[token]?status=done`, `/password/reset/${token}?status=done`, {
  shallow: true,
});

This is the only way i manage to make it work by filling up the query in both href and as

If i put the query part only on the href argument, component state is updated but url isn't, i don't know if this is intended behaviour or not.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

irrigator picture irrigator  路  3Comments

knipferrc picture knipferrc  路  3Comments

renatorib picture renatorib  路  3Comments

pie6k picture pie6k  路  3Comments

rauchg picture rauchg  路  3Comments