Skip to content

Commit

Permalink
Allow scroll prevention on hash change (#31921)
Browse files Browse the repository at this point in the history
* Allow scroll prevention on hash change

Currently, `scrollToHash` is performed on every hash change, even when this change is caused by `<Link scroll={false} {...props} />`.
This change prevents scrolling in this case and allows users to specify the desired scrolling behavior in the router's `hashChangeComplete` event.

* Add test case and apply fixes

Co-authored-by: JJ Kasper <jj@jjsweb.site>
  • Loading branch information
wouterraateland and ijjk committed Feb 7, 2022
1 parent 41706d6 commit b49717f
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 8 deletions.
5 changes: 0 additions & 5 deletions packages/next/client/link.tsx
Expand Up @@ -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,
Expand Down
11 changes: 8 additions & 3 deletions packages/next/shared/lib/router/router.ts
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions test/integration/client-navigation/pages/nav/hash-changes.js
Expand Up @@ -27,6 +27,11 @@ const HashChanges = ({ count }) => {
<Link href="#name-item-400">
<a id="scroll-to-name-item-400">Go to name item 400</a>
</Link>
<Link href="#name-item-400" scroll={false}>
<a id="scroll-to-name-item-400-no-scroll">
Go to name item 400 (no scroll)
</a>
</Link>
<p>COUNT: {count}</p>
{Array.from({ length: 500 }, (x, i) => i + 1).map((i) => {
return (
Expand Down
11 changes: 11 additions & 0 deletions test/integration/client-navigation/test/index.test.js
Expand Up @@ -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 {
Expand Down

0 comments on commit b49717f

Please sign in to comment.