Skip to content

Commit 6490252

Browse files
authored
Don't pushState when already on the url (#42735)
Solves the case where you click a link to the page you're on already that pushes additional history entries, uses replaceState for that instead. This mirrors the default `<a>` behavior. ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [x] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
1 parent f612acf commit 6490252

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

packages/next/client/components/app-router.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,10 @@ function Router({
293293
// __NA is used to identify if the history entry can be handled by the app-router.
294294
// __N is used to identify if the history entry can be handled by the old router.
295295
const historyState = { __NA: true, tree }
296-
if (pushRef.pendingPush) {
296+
if (
297+
pushRef.pendingPush &&
298+
createHrefFromUrl(new URL(window.location.href)) !== canonicalUrl
299+
) {
297300
// This intentionally mutates React state, pushRef is overwritten to ensure additional push/replace calls do not trigger an additional history entry.
298301
pushRef.pendingPush = false
299302

test/e2e/app-dir/index.test.ts

+23
Original file line numberDiff line numberDiff line change
@@ -2135,6 +2135,29 @@ describe('app dir', () => {
21352135
.text()
21362136
).toBe(`About page`)
21372137
})
2138+
it('should not do additional pushState when already on the page', async () => {
2139+
const browser = await webdriver(next.url, '/linking/about')
2140+
const goToLinkingPage = async () => {
2141+
expect(
2142+
await browser
2143+
.elementByCss('a[href="/linking"]')
2144+
.click()
2145+
.waitForElementByCss('#home-page')
2146+
.text()
2147+
).toBe(`Home page`)
2148+
}
2149+
2150+
await goToLinkingPage()
2151+
await waitFor(1000)
2152+
await goToLinkingPage()
2153+
await waitFor(1000)
2154+
await goToLinkingPage()
2155+
await waitFor(1000)
2156+
2157+
expect(
2158+
await browser.back().waitForElementByCss('#about-page', 2000).text()
2159+
).toBe(`About page`)
2160+
})
21382161
})
21392162

21402163
describe('not-found', () => {

0 commit comments

Comments
 (0)