question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Scroll restoration no longer works on popState when using shouldUpdateScroll browser API to orchestrate page transitions

See original GitHub issue

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:

  1. 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
  2. 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!

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
vladarcommented, Oct 9, 2020

Thank you for opening this @blimpmason

And big kudos for the excellent reproduction! ❤️

I’ve bisected it and seems that it was introduced in gatsby@2.21.15: compare.

The only suspicious PR is this one: #21626 and it is marked as a breaking change (but for the plugin not for gatsby). So this interesting.

I didn’t have a chance yet to see what we can do here, so if someone is ready to tackle this - we are happy to accept a PR with a fix!

0reactions
blimpmasoncommented, Dec 29, 2020

Thanks @vrabe and @vladar! I just updated to gastby@2.29.0-next.1 to test the fix and it looks like the scroll coordinates are now coming back as an array as expected so scroll position can be used once again without modifying the gatsby-browser shouldUpdateScroll function.

Unfortunately I’m still experiencing an issue in which the page scrolls to the restored position before the setTimeout has completed — it seems the router is ignoring the shouldUpdateScroll logic.

Example here: https://fix-test--gatsby-scroll-restoration-issue.netlify.app/. You can see the issue when you scroll to the bottom of page 1, click the link to page 2 and then hit the browser back button.

I will open a new issue to address this issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

History API - Scroll restoration - Chrome Developers
An update to the History API to prevent unsightly scroll jumping. ... app does transitions, or changes the contents of the page in...
Read more >
How to fix Gatsby JS Link component retaining scroll position ...
10 and the Link components are retaining the scroll positions of the previous page and not scrolling back to the top when they're...
Read more >
Scroll Restoration - Gatsby
This property allows restoring a user's scroll position when navigating to a new page. Gatsby will handle scroll restoration for you in most...
Read more >
721262 - Chrome scroll restoration does not work ... - Monorail
Issue 721262: Chrome scroll restoration does not work when the "next" page is shorter than the "previous" page. Reported by schedule erik.
Read more >
Ryan Florence on Twitter: "For those curious, here's the ...
Kinda looks like that scroll restoration is animated on the last transition, but it's not (I hate that ux), it's the transform-origin of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found