next.js
next.js copied to clipboard
`next/link` does not format the URL string properly with URL object for a dynamic route.
Verify canary release
- [X] I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 22.1.0: Sun Oct 9 20:15:09 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T6000
Binaries:
Node: 18.12.1
npm: 9.1.1
Yarn: N/A
pnpm: N/A
Relevant packages:
next: 13.0.3-canary.2
eslint-config-next: 13.0.2
react: 18.2.0
react-dom: 18.2.0
What browser are you using? (if relevant)
Chrome 107.0.5304.87 (Official Build) (arm64)
How are you deploying your application? (if relevant)
next dev
and next start
Describe the Bug
Based on NextJS beta and stable docs:
- https://beta.nextjs.org/docs/api-reference/components/link#href
- https://nextjs.org/docs/api-reference/next/link#with-url-object
A URL object can be used inside Link
in the following way.
<Link
href={{
pathname: '/blog/[slug]',
query: { slug: 'my-post' },
}}
>
Which will generate a link to /blog/my-post
.
However, it instead generates a link to /blog/[slug]?slug=my-post
.
Expected Behavior
Link
should generate a link to /blog/my-post
.
Link to reproduction - Issues with a link to complete (but minimal) reproduction code will be addressed faster
https://stackblitz.com/edit/vercel-next-js-s8tr8n?file=app/page.tsx
To Reproduce
- Create a new app with
npx create-next-app@latest --experimental-app
. - Add the following code to
app/page.tsx
.
<Link href={{ pathname: "/blog/[slug]", query: { slug: "my-post" } }}>
Hyperlink
</Link>
- Create
app/blog/[slug]/page.tsx
and add the following code to it.
export default function Page({ params }: { params: { slug: string } }) {
const { slug } = params;
return (
<div>
<h1>{slug}</h1>
</div>
);
}
- Run the server and visit the 'Hyperlink` from the main page and check out the URL.
I am confirming that I am seeing the same issue.
The new router no longer has a concept of dynamic segments vs non dynamic segments client-side, it also solves the query
vs params
issue that has come up before, basically query
no longer holds the dynamic segments.
Something like this will work:
<Link href={{ pathname: "/blog/my-post" }}>
Hyperlink
</Link>
We'll have to add an error when a dynamic segment is referenced in this way in development for app
@hanneslund.
The new router no longer has a concept of dynamic segments vs non dynamic segments client-side, it also solves the
query
vsparams
issue that has come up before, basicallyquery
no longer holds the dynamic segments.Something like this will work:
<Link href={{ pathname: "/blog/my-post" }}> Hyperlink </Link>
We'll have to add an error when a dynamic segment is referenced in this way in development for
app
@hanneslund.
So does that mean this setup in the following example will not work anymore? :
// an object in a constants file that i import into the component
const routes = {
overview: {
path: '/risk-rules/[id]',
}
}
const { id } = router.query
<Button
onClick={() => router.push({
pathname: routes.overview.path, // < ----
query: { id }, // <----
})}
/>
So what would the best practice be now to make it equivalent? would it be just writing it as a template literal or something else? Because its not as nice to share my paths with other files doing it as a template literal:
<Button
onClick={() => router.push({
pathname: `/risk-rules/${id}`,
})}
/>
This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.