scroll={false}
doesn't maintain the scroll of the previous page; it doesn't change the scroll at all which means the scroll would be that of the page you are linking from. You can use scroll={false}
to override the default behavior of setting the scrollY to 0, so you can implement your own behavior.
Here's how I implemented restoring the scroll position. This is very similar to Max william's answer, but using useRef
instead of useState
. We are using useRef
instead of useState
because useRef
does not cause a re-render whenever its value is mutated, unlike useState
. We are going to be updating the value to the current scroll position every time the scroll is changed by the user, which would mean a ton of useless re-renders if we were to use useState.
First, define a UserContext component to easily pass the scroll data from the _app.js component to wherever you need:
import { createContext } from 'react';
const UserContext = createContext();
export default UserContext;
Then, in your _app.js component, wrap your pages with the UserContext and create a useRef attribute to store the scroll position.
import { useRef } from 'react';
import UserContext from '../components/context'
function MyApp({ Component, pageProps }) {
const scrollRef = useRef({
scrollPos: 0
});
return (
<Layout>
<UserContext.Provider value={{ scrollRef: scrollRef }}>
<Component {...pageProps} />
</UserContext.Provider>
</Layout>
)
}
export default MyApp
Then inside whichever page component you are wanting to restore the scroll position (that is, the page that you want to return to and see the same scroll position as when you left), you can put this code to set the scroll position of the page and bind a scroll event to a function to update the stored scroll position.
import UserContext from '../components/context'
import { useContext } from 'react';
export default function YourPageComponent() {
const { scrollRef } = useContext(UserContext);
React.useEffect(() => {
//called when the component has been mounted, sets the scroll to the currently stored scroll position
window.scrollTo(0, scrollRef.current.scrollPos);
const handleScrollPos = () => {
//every time the window is scrolled, update the reference. This will not cause a re-render, meaning smooth uninterrupted scrolling.
scrollRef.current.scrollPos = window.scrollY
};
window.addEventListener('scroll', handleScrollPos);
return () => {
//remove event listener on unmount
window.removeEventListener('scroll', handleScrollPos);
};
});
return (
//your content
)
}
The last little thing is to use scroll={false}
on your Link component that links back to YourPageComponent. This is so next.js doesn't automatically set the scroll to 0, overriding everything we've done.
Credit to Max william's answer to the majority of the structure, my main change is using useRef. I also added some explanations, I hope it's helpful!