diff --git a/packages/next/client/link.tsx b/packages/next/client/link.tsx index 9a7f65b52997b92..9bb634d251adc02 100644 --- a/packages/next/client/link.tsx +++ b/packages/next/client/link.tsx @@ -96,11 +96,6 @@ function linkClicked( e.preventDefault() - // avoid scroll for urls with anchor refs - if (scroll == null && as.indexOf('#') >= 0) { - scroll = false - } - // replace state instead of push if prop is present router[replace ? 'replace' : 'push'](href, as, { shallow, diff --git a/packages/next/shared/lib/router/router.ts b/packages/next/shared/lib/router/router.ts index 9a41567ba0bface..ed80980691fd1a8 100644 --- a/packages/next/shared/lib/router/router.ts +++ b/packages/next/shared/lib/router/router.ts @@ -1009,7 +1009,7 @@ export default class Router implements BaseRouter { performance.mark('routeChange') } - const { shallow = false } = options + const { shallow = false, scroll = true } = options const routeProps = { shallow } if (this._inFlightRoute) { @@ -1045,8 +1045,13 @@ export default class Router implements BaseRouter { this.asPath = cleanedAs Router.events.emit('hashChangeStart', as, routeProps) // TODO: do we need the resolved href when only a hash change? - this.changeState(method, url, as, options) - this.scrollToHash(cleanedAs) + this.changeState(method, url, as, { + ...options, + scroll: false, + }) + if (scroll) { + this.scrollToHash(cleanedAs) + } this.notify(this.components[this.route], null) Router.events.emit('hashChangeComplete', as, routeProps) return true diff --git a/test/integration/client-navigation/pages/nav/hash-changes.js b/test/integration/client-navigation/pages/nav/hash-changes.js index e76f3a22d89fc34..67c9a35cde53fd7 100644 --- a/test/integration/client-navigation/pages/nav/hash-changes.js +++ b/test/integration/client-navigation/pages/nav/hash-changes.js @@ -27,6 +27,11 @@ const HashChanges = ({ count }) => { Go to name item 400 + + + Go to name item 400 (no scroll) + +

COUNT: {count}

{Array.from({ length: 500 }, (x, i) => i + 1).map((i) => { return ( diff --git a/test/integration/client-navigation/test/index.test.js b/test/integration/client-navigation/test/index.test.js index 4a6921dfdd4466d..f89aeed941ee702 100644 --- a/test/integration/client-navigation/test/index.test.js +++ b/test/integration/client-navigation/test/index.test.js @@ -625,6 +625,17 @@ describe('Client Navigation', () => { } }) + it('should not scroll to hash when scroll={false} is set', async () => { + const browser = await webdriver(context.appPort, '/nav/hash-changes') + const curScroll = await browser.eval( + 'document.documentElement.scrollTop' + ) + await browser.elementByCss('#scroll-to-name-item-400-no-scroll').click() + expect(curScroll).toBe( + await browser.eval('document.documentElement.scrollTop') + ) + }) + it('should scroll to the specified position on the same page with a name property', async () => { let browser try {