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', () => {