Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
App directory next/link dynamic href dev error (#43074)
Co-authored-by: Tim Neutkens <tim@timneutkens.nl> Fixes #42715
- Loading branch information
1 parent
c16d4be
commit 0f195f0
Showing
9 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Dynamic `href` is not supported in the `/app` directory | ||
|
||
#### Why This Error Occurred | ||
|
||
You have tried to use a dynamic `href` with `next/link` in the `app` directory. This is not supported as the new client-side router no longer uses a mapping of dynamic routes -> url, instead it always leverages the url. | ||
|
||
#### Possible Ways to Fix It | ||
|
||
**Before** | ||
|
||
```jsx | ||
<Link | ||
href={{ | ||
pathname: '/route/[slug]', | ||
query: { slug: '1' }, | ||
}} | ||
> | ||
link | ||
</Link> | ||
``` | ||
|
||
Or | ||
|
||
```jsx | ||
<Link href="/route/[slug]?slug=1">link</Link> | ||
``` | ||
|
||
**After** | ||
|
||
```jsx | ||
<Link href="/route/1">link</Link> | ||
``` | ||
|
||
### Useful Links | ||
|
||
[`next/link` documentation](https://beta.nextjs.org/docs/api-reference/components/link#href) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { createNext, FileRef } from 'e2e-utils' | ||
import { NextInstance } from 'test/lib/next-modes/base' | ||
import { getRedboxDescription, hasRedbox } from 'next-test-utils' | ||
import path from 'path' | ||
import webdriver from 'next-webdriver' | ||
|
||
describe('dynamic-href', () => { | ||
const isDev = (global as any).isNextDev | ||
if ((global as any).isNextDeploy) { | ||
it('should skip next deploy for now', () => {}) | ||
return | ||
} | ||
|
||
let next: NextInstance | ||
|
||
beforeAll(async () => { | ||
next = await createNext({ | ||
files: new FileRef(path.join(__dirname, 'dynamic-href')), | ||
dependencies: { | ||
react: 'experimental', | ||
'react-dom': 'experimental', | ||
}, | ||
}) | ||
}) | ||
afterAll(() => next.destroy()) | ||
|
||
if (isDev) { | ||
it('should error when using dynamic href.pathname in app dir', async () => { | ||
const browser = await webdriver(next.url, '/object') | ||
|
||
// Error should show up | ||
expect(await hasRedbox(browser, true)).toBeTrue() | ||
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot( | ||
`"Error: Dynamic href \`/object/[slug]\` found in <Link> while using the \`/app\` router, this is not supported. Read more: https://nextjs.org/docs/messages/app-dir-dynamic-href"` | ||
) | ||
|
||
// Fix error | ||
const pageContent = await next.readFile('app/object/page.js') | ||
await next.patchFile( | ||
'app/object/page.js', | ||
pageContent.replace( | ||
"pathname: '/object/[slug]'", | ||
"pathname: '/object/slug'" | ||
) | ||
) | ||
expect(await browser.waitForElementByCss('#link').text()).toBe('to slug') | ||
|
||
// Navigate to new page | ||
await browser.elementByCss('#link').click() | ||
expect(await browser.waitForElementByCss('#pathname').text()).toBe( | ||
'/object/slug' | ||
) | ||
expect(await browser.elementByCss('#slug').text()).toBe('1') | ||
}) | ||
|
||
it('should error when using dynamic href in app dir', async () => { | ||
const browser = await webdriver(next.url, '/string') | ||
|
||
// Error should show up | ||
expect(await hasRedbox(browser, true)).toBeTrue() | ||
expect(await getRedboxDescription(browser)).toMatchInlineSnapshot( | ||
`"Error: Dynamic href \`/object/[slug]\` found in <Link> while using the \`/app\` router, this is not supported. Read more: https://nextjs.org/docs/messages/app-dir-dynamic-href"` | ||
) | ||
}) | ||
} else { | ||
it('should not error on /object in prod', async () => { | ||
const browser = await webdriver(next.url, '/object') | ||
expect(await browser.elementByCss('#link').text()).toBe('to slug') | ||
}) | ||
it('should not error on /string in prod', async () => { | ||
const browser = await webdriver(next.url, '/string') | ||
expect(await browser.elementByCss('#link').text()).toBe('to slug') | ||
}) | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export default function Root({ children }) { | ||
return ( | ||
<html> | ||
<head> | ||
<title>Hello World</title> | ||
</head> | ||
<body>{children}</body> | ||
</html> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
'use client' | ||
import { usePathname, useSearchParams } from 'next/navigation' | ||
|
||
export default function Page() { | ||
const pathname = usePathname() | ||
const searchParams = useSearchParams() | ||
|
||
return ( | ||
<> | ||
<p id="pathname">{pathname}</p> | ||
<p id="slug">{searchParams.get('slug')}</p> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import Link from 'next/link' | ||
|
||
export default function HomePage() { | ||
return ( | ||
<Link | ||
id="link" | ||
href={{ | ||
pathname: '/object/[slug]', | ||
query: { slug: '1' }, | ||
}} | ||
> | ||
to slug | ||
</Link> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import Link from 'next/link' | ||
|
||
export default function HomePage() { | ||
return ( | ||
<Link id="link" href="/object/[slug]"> | ||
to slug | ||
</Link> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
experimental: { | ||
appDir: true, | ||
}, | ||
} |