From 6490252b40e191154e04dfedab05693495e67297 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 10 Nov 2022 19:06:57 +0100 Subject: [PATCH] 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 `` 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) --- .../next/client/components/app-router.tsx | 5 +++- test/e2e/app-dir/index.test.ts | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/next/client/components/app-router.tsx b/packages/next/client/components/app-router.tsx index 9a9d1284222a..634c4ee55a53 100644 --- a/packages/next/client/components/app-router.tsx +++ b/packages/next/client/components/app-router.tsx @@ -293,7 +293,10 @@ function Router({ // __NA is used to identify if the history entry can be handled by the app-router. // __N is used to identify if the history entry can be handled by the old router. const historyState = { __NA: true, tree } - if (pushRef.pendingPush) { + if ( + pushRef.pendingPush && + createHrefFromUrl(new URL(window.location.href)) !== canonicalUrl + ) { // This intentionally mutates React state, pushRef is overwritten to ensure additional push/replace calls do not trigger an additional history entry. pushRef.pendingPush = false diff --git a/test/e2e/app-dir/index.test.ts b/test/e2e/app-dir/index.test.ts index 8e91c7a4b6a6..14a1da1c295d 100644 --- a/test/e2e/app-dir/index.test.ts +++ b/test/e2e/app-dir/index.test.ts @@ -2135,6 +2135,29 @@ describe('app dir', () => { .text() ).toBe(`About page`) }) + it('should not do additional pushState when already on the page', async () => { + const browser = await webdriver(next.url, '/linking/about') + const goToLinkingPage = async () => { + expect( + await browser + .elementByCss('a[href="/linking"]') + .click() + .waitForElementByCss('#home-page') + .text() + ).toBe(`Home page`) + } + + await goToLinkingPage() + await waitFor(1000) + await goToLinkingPage() + await waitFor(1000) + await goToLinkingPage() + await waitFor(1000) + + expect( + await browser.back().waitForElementByCss('#about-page', 2000).text() + ).toBe(`About page`) + }) }) describe('not-found', () => {