Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Router Error Events in Shallow Routing by Skipping cancelHandler Creation #61771

Merged
merged 15 commits into from
Feb 28, 2024
4 changes: 2 additions & 2 deletions packages/next/src/shared/lib/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1943,13 +1943,13 @@ export default class Router implements BaseRouter {
let route = requestedRoute

try {
const handleCancelled = getCancelledHandler({ route, router: this })

let existingInfo: PrivateRouteInfo | undefined = this.components[route]
if (routeProps.shallow && existingInfo && this.route === route) {
return existingInfo
}

const handleCancelled = getCancelledHandler({ route, router: this })

if (hasMiddleware) {
existingInfo = undefined
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'

export default function Page() {
const router = useRouter()

const [routeState, setRouteResult] = useState({
completed: 0,
errors: 0,
})
useEffect(() => {
const increaseErrorCount = () =>
setRouteResult((state) => ({ ...state, errors: state.errors + 1 }))
const increaseRouteComplete = () =>
setRouteResult((state) => ({ ...state, completed: state.completed + 1 }))
router.events.on('routeChangeError', increaseErrorCount)
router.events.on('routeChangeComplete', increaseRouteComplete)

return () => {
router.events.off('routeChangeError', increaseErrorCount)
router.events.off('routeChangeComplete', increaseRouteComplete)
}
})

return (
<>
<div id="routeState">{JSON.stringify(routeState)}</div>
<Link href="?prop=foo" id="link" shallow={true}>
Click me
</Link>
<button
id="router-replace"
onClick={() => {
router.replace('?prop=baz', undefined, { shallow: true })
}}
>
Push me
</button>
</>
)
}
16 changes: 16 additions & 0 deletions test/development/pages-dir/client-navigation/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,22 @@ createNextDescribe(
await browser.close()
}
})

it('router.replace with shallow=true shall not throw route cancelled errors', async () => {
const browser = await webdriver(next.appPort, '/nav/query-only-shallow')
try {
await browser.elementByCss('#router-replace').click()
// the error occurs on every replace() after the first one
await browser.elementByCss('#router-replace').click()

await check(
() => browser.waitForElementByCss('#routeState').text(),
'{"completed":2,"errors":0}'
)
} finally {
await browser.close()
}
})
})

describe('with getInitialProp redirect', () => {
Expand Down