-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Description
Description
At some point in the last six months or so the shouldUpdateScroll browser API hook and related functionality seems to have been changed under the hood and introduced breaking changes to scroll restoration for Gatsby sites that use a simple animated page transition implementation (as introduced by @ryanwiemer: https://github.com/ryanwiemer/gatsby-using-page-transitions).
I'd guess there could be a significant number of sites affected considering the many themes and starters that make use of this page transition technique.
Here's the bit of code that gets added to gatsby-browser.js to support scroll restoration with animated page transitions (which rely on gatsby-plugin-layout and your animation library of choice):
const transitionDelay = 600;
export const shouldUpdateScroll = ({
routerProps: { location },
getSavedScrollPosition
}) => {
if (location.action === "PUSH") {
window.setTimeout(() => window.scrollTo(0, 0), transitionDelay);
} else {
const savedPosition = getSavedScrollPosition(location);
window.setTimeout(
() => window.scrollTo(...(savedPosition || [0, 0])),
transitionDelay
);
}
return false;
};
Essentially, scroll restoration no longer works correctly on popState when page transitions are involved.
Console logging the savedPosition that gets retrieved in the code snippet above always returns 0. There are two issues here:
- The function is returning a single number rather than an
[x, y]coordinate array as expected per the documentation here: https://www.gatsbyjs.com/docs/browser-apis/#shouldUpdateScroll - The function always returns 0 despite the scroll position saved in session storage, so even when modifying the code above to
window.scrollTo(0, savedPosition || 0), the user is always sent to the top of the page when using browser back or forward buttons.
Steps to reproduce
On the demo link below, scroll all the way to the bottom of the index page, click the link to Page 2, and then click the browser back button. You will land back at the top of the index page rather than where you left off at the bottom.
Demo link: https://gatsby-scroll-restoration-issue.netlify.app/
Demo repo: https://github.com/blimpmason/gatsby-scroll-restoration-issue
Expected result
On the comparison demo link below (which uses an older version of Gatsby, v2.19.43, along with matching dependency versions), scroll all the way to the bottom of the index page, click the link to Page 2, and then click the browser back button. You should always land you exactly where you were at the bottom of the index page.
Demo link (working comparison): https://gatsby-scroll-restoration-issue-comparison.netlify.app/
Demo repo (working comparison): https://github.com/blimpmason/gatsby-scroll-restoration-issue-comparison
Actual result
You always end up back at the top of the page.
Environment
System:
OS: macOS 10.15.6
CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 14.4.0 - ~/.nvm/versions/node/v14.4.0/bin/node
Yarn: 1.22.4 - /usr/local/bin/yarn
npm: 6.14.5 - ~/.nvm/versions/node/v14.4.0/bin/npm
Languages:
Python: 2.7.16 - /usr/bin/python
Browsers:
Chrome: 85.0.4183.121
Firefox: 81.0
Safari: 14.0
npmPackages:
gatsby: ^2.24.72 => 2.24.72
gatsby-image: ^2.4.20 => 2.4.20
gatsby-plugin-layout: ^1.3.13 => 1.3.13
gatsby-plugin-manifest: ^2.4.33 => 2.4.33
gatsby-plugin-offline: ^3.2.30 => 3.2.30
gatsby-plugin-react-helmet: ^3.3.12 => 3.3.12
gatsby-plugin-sharp: ^2.6.38 => 2.6.38
gatsby-source-filesystem: ^2.3.32 => 2.3.32
gatsby-transformer-sharp: ^2.5.16 => 2.5.16
npmGlobalPackages:
gatsby-cli: 2.12.80
Hi to @wardpeet and @blainekasten who may have seen my misplaced comments on this issue in a merged PR thread!