interception routes: fix interception for dynamic routes (#58198)
This PR fixes the bug in which interception routes of the form `(.)[param]` would not intercept navigations. The bug happened because we would not create a dynamic route matcher for the intercepted route, so we would never match the correct dynamic route when hitting the server, falling back to the base one. The fix consists of fixing the logic that checks for a dynamic route so that it checks the correct path when handling an interception route. There's probably a better fix here, advice welcome fixes #52533
This commit is contained in:
parent
a6a8c8422c
commit
536d2dbc44
8 changed files with 105 additions and 1 deletions
|
@ -4,6 +4,10 @@ import { isDynamicRoute } from '../shared/lib/router/utils'
|
|||
import { removeTrailingSlash } from '../shared/lib/router/utils/remove-trailing-slash'
|
||||
import type { Redirect } from './load-custom-routes'
|
||||
import { tryToParsePath } from './try-to-parse-path'
|
||||
import {
|
||||
extractInterceptionRouteInformation,
|
||||
isInterceptionRouteAppPath,
|
||||
} from '../server/future/helpers/interception-routes'
|
||||
|
||||
export function createClientRouterFilter(
|
||||
paths: string[],
|
||||
|
@ -16,8 +20,12 @@ export function createClientRouterFilter(
|
|||
const staticPaths = new Set<string>()
|
||||
const dynamicPaths = new Set<string>()
|
||||
|
||||
for (const path of paths) {
|
||||
for (let path of paths) {
|
||||
if (isDynamicRoute(path)) {
|
||||
if (isInterceptionRouteAppPath(path)) {
|
||||
path = extractInterceptionRouteInformation(path).interceptedRoute
|
||||
}
|
||||
|
||||
let subPath = ''
|
||||
const pathParts = path.split('/')
|
||||
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
import {
|
||||
extractInterceptionRouteInformation,
|
||||
isInterceptionRouteAppPath,
|
||||
} from '../../../../server/future/helpers/interception-routes'
|
||||
|
||||
// Identify /[param]/ in route string
|
||||
const TEST_ROUTE = /\/\[[^/]+?\](?=\/|$)/
|
||||
|
||||
export function isDynamicRoute(route: string): boolean {
|
||||
if (isInterceptionRouteAppPath(route)) {
|
||||
route = extractInterceptionRouteInformation(route).interceptedRoute
|
||||
}
|
||||
|
||||
return TEST_ROUTE.test(route)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
export default function Page({ params: { id } }) {
|
||||
return (
|
||||
<div>
|
||||
<h2>intercepting-siblings</h2>
|
||||
<p id="intercepted-sibling">{id}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export default function Default() {
|
||||
return <div>default</div>
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
export default function Page({ params: { id } }) {
|
||||
return (
|
||||
<div>
|
||||
<h2>main slot</h2>
|
||||
<p id="main-slot">{id}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import Link from 'next/link'
|
||||
|
||||
export default function Layout({ children, modal }) {
|
||||
return (
|
||||
<div>
|
||||
<h1>intercepting-siblings</h1>
|
||||
<div style={{ border: '1px solid black', padding: '1rem' }}>
|
||||
{children}
|
||||
</div>
|
||||
<hr />
|
||||
<div style={{ border: '1px solid black', padding: '1rem' }}>{modal}</div>
|
||||
<h1>links</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<Link href="/intercepting-siblings">/intercepting-siblings</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/intercepting-siblings/1">/intercepting-siblings/1</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/intercepting-siblings/2">/intercepting-siblings/2</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/intercepting-siblings/3">/intercepting-siblings/3</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return <div>main page</div>
|
||||
}
|
|
@ -751,6 +751,42 @@ createNextDescribe(
|
|||
'intercepted'
|
||||
)
|
||||
})
|
||||
|
||||
it('should support intercepting local dynamic sibling routes', async () => {
|
||||
const browser = await next.browser('/intercepting-siblings')
|
||||
|
||||
await check(
|
||||
() =>
|
||||
browser
|
||||
.elementByCss('[href="/intercepting-siblings/1"]')
|
||||
.click()
|
||||
.waitForElementByCss('#intercepted-sibling')
|
||||
.text(),
|
||||
'1'
|
||||
)
|
||||
await check(
|
||||
() =>
|
||||
browser
|
||||
.elementByCss('[href="/intercepting-siblings/2"]')
|
||||
.click()
|
||||
.waitForElementByCss('#intercepted-sibling')
|
||||
.text(),
|
||||
'2'
|
||||
)
|
||||
await check(
|
||||
() =>
|
||||
browser
|
||||
.elementByCss('[href="/intercepting-siblings/3"]')
|
||||
.click()
|
||||
.waitForElementByCss('#intercepted-sibling')
|
||||
.text(),
|
||||
'3'
|
||||
)
|
||||
|
||||
await next.browser('/intercepting-siblings/1')
|
||||
|
||||
await check(() => browser.waitForElementByCss('#main-slot').text(), '1')
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue