I was easily able to reproduce the issue with React 17, although I wasn't able to recreate it using only React. And although I wasn't able to determine any causes, I was able to find a solution. I'll drop it here in case anybody encounters the same issue.
I discovered that the issue only occurs if I explicitly create a smooth-wrapper and smooth-content like so:
() => {
SmoothScroller.create()
//this doesn't work
return (
<div id="smooth-wrapper">
<div id="smooth-content">{children}</div>
</div> //
);
//if I remove the explicitly created wrappers, this would work fine
//but we would lose control of fixed elements (since they'd no longer be outside the wrapper)
return children;
}
To fix the issue, I moved the ScrollSmoother.create() into gatsby-browser while leaving the smooth-wrapper and smooth-content in place. This fixes the jumping while retaining control of fixed elements, however the scroller won't always be up-to-date with the wrapper and therefore sometimes just won't scroll. This can be resolved pretty easily by adding a useEffect that refreshes the scroller anytime the scroll component updates.
That leaves the final solution as follows:
//in gatsby-browser
SmoothScroller.create()
//in Scroll component
() => {
useEffect(() => {
SmoothScroller.get().refresh()
})
return (
<div id="smooth-wrapper">
<div id="smooth-content">{children}</div>
</div> //
);
}