Disable Next.js scroll restoration #5026
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I am adding a hack. I don't want to keep it forever. If someone in the future finds this PR and it causes some pains (like with upgrading Next), feel free to revert it but ping me so I can add it back. Eventually this hack shouldn't be needed because it's really due to how the current Next.js router works, and it's a known issue that should be resolved by the upcoming one.
The problematic behavior is this. Basically, if you scroll even a little bit, the Back gesture no longer shows a preview of the previous/next page during the swipe. This feels confusing and disorienting.
RPReplay_Final1662727484.MP4
I only have a vague understanding of the issue, but here's what I gather so far:
startTransition
.scrollTo
. Here is a related post but with the opposite problem. If someone wants to dig in why Next.js's custom scroll restoration breaks that heuristic, be my guest! Then maybe we can fix that part and remove my hack.popstate
synchronously update the UI. Which this PR (almost) does:startTransition
duringpopstate
, which I believe should not be happening in the first place. Transitions should be used for navigations like links, not for the Back button click. We already fixed something similar in vanilla React in Add more non-React events to the priority list facebook/react#20774, so I think Next.js should have some kind of similar behavior.scrollTo()
. For navigations to new links this is 100% reasonable (we want to scroll to top). But I don't think it should be doing this onpopstate
since my whole point is that I wanted to let the browser do it! So I disabled the codepath that tries toscrollTo(0, 0)
onpopstate
, since that interferes with what the browser does.This seems enough to fix the Safari issue on iOS.
Unfortunately this introduces DEV-only jumps on Back/Forward because in DEV, there's not just a Promise tick but an actual refetch on every navigation (even Back navigation). This seems unfortunate.
Overall, all of this is super hacky and I'm happy to get rid of this when/if the new Next.js router fixes this. For now, I'm ok maintaining this hack.