From 57d8af857ab1f2d03148560214ff6debfcb23698 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 28 Jun 2018 20:56:18 +0200 Subject: [PATCH] Make sure hashchanges get triggered (#4676) When clicking a next/link with a hash (#something) multiple times, it wouldn't keep the scrolling behavior browsers have. This makes sure we correctly trigger it. --- lib/router/router.js | 11 ++++++++ .../basic/pages/nav/hash-changes.js | 6 +++++ .../basic/test/client-navigation.js | 25 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/lib/router/router.js b/lib/router/router.js index 174f9592..3cb299f7 100644 --- a/lib/router/router.js +++ b/lib/router/router.js @@ -292,6 +292,11 @@ export default class Router { const [ oldUrlNoHash, oldHash ] = this.asPath.split('#') const [ newUrlNoHash, newHash ] = as.split('#') + // Makes sure we scroll to the provided hash if the url/hash are the same + if (newHash && (oldUrlNoHash === newUrlNoHash) && (oldHash === newHash)) { + return true + } + // If the urls are change, there's more than a hash change if (oldUrlNoHash !== newUrlNoHash) { return false @@ -306,6 +311,12 @@ export default class Router { scrollToHash (as) { const [ , hash ] = as.split('#') + // Scroll to top if the hash is just `#` with no value + if (hash === '') { + window.scrollTo(0, 0) + return + } + const el = document.getElementById(hash) if (el) { el.scrollIntoView() diff --git a/test/integration/basic/pages/nav/hash-changes.js b/test/integration/basic/pages/nav/hash-changes.js index 077377ca..22a5a548 100644 --- a/test/integration/basic/pages/nav/hash-changes.js +++ b/test/integration/basic/pages/nav/hash-changes.js @@ -24,7 +24,13 @@ export default class SelfReload extends Component { Via Empty Hash + + Go to item 400 +

COUNT: {this.props.count}

+ {Array.from({length: 500}, (x, i) => i + 1).map(i => { + return
{i}
+ })} ) } diff --git a/test/integration/basic/test/client-navigation.js b/test/integration/basic/test/client-navigation.js index 958ec36c..474355b7 100644 --- a/test/integration/basic/test/client-navigation.js +++ b/test/integration/basic/test/client-navigation.js @@ -230,6 +230,31 @@ export default (context, render) => { browser.close() }) + + it('should scroll to the specified position', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav/hash-changes') + + // Scrolls to item 400 on the page + const scrollPosition = await browser + .elementByCss('#scroll-to-item-400').click() + .eval('window.pageYOffset') + + expect(scrollPosition).toBe(7258) + + // Scrolls back to top when scrolling to `#` with no value. + const scrollPositionAfterEmptyHash = await browser + .elementByCss('#via-empty-hash').click() + .eval('window.pageYOffset') + + expect(scrollPositionAfterEmptyHash).toBe(0) + } finally { + if (browser) { + browser.close() + } + } + }) }) describe('when hash change via A tag', () => {