Skip to content

Instantly share code, notes, and snippets.

@GusRuss89
Last active August 27, 2023 12:51
Show Gist options
  • Save GusRuss89/df05ea25310043fc38a5e2ba3cb0c016 to your computer and use it in GitHub Desktop.
Save GusRuss89/df05ea25310043fc38a5e2ba3cb0c016 to your computer and use it in GitHub Desktop.
Nextjs - keep state and scroll position between page transitions. Described in detail here - https://medium.com/@angus.russell89/next-js-keep-page-components-mounted-between-page-transitions-and-maintain-scroll-position-205b34539a26
import React, { useRef, useEffect, memo } from 'react'
import { useRouter } from 'next/router'
const ROUTES_TO_RETAIN = ['/dashboard', '/top', '/recent', 'my-posts']
const App = ({ Component, pageProps }) => {
const router = useRouter()
const retainedComponents = useRef({})
const isRetainableRoute = ROUTES_TO_RETAIN.includes(router.asPath)
// Add Component to retainedComponents if we haven't got it already
if (isRetainableRoute && !retainedComponents.current[router.asPath]) {
const MemoComponent = memo(Component)
retainedComponents.current[router.asPath] = {
component: <MemoComponent {...pageProps} />,
scrollPos: 0
}
}
// Save the scroll position of current page before leaving
const handleRouteChangeStart = url => {
if (isRetainableRoute) {
retainedComponents.current[router.asPath].scrollPos = window.scrollY
}
}
// Save scroll position - requires an up-to-date router.asPath
useEffect(() => {
router.events.on('routeChangeStart', handleRouteChangeStart)
return () => {
router.events.off('routeChangeStart', handleRouteChangeStart)
}
}, [router.asPath])
// Scroll to the saved position when we load a retained component
useEffect(() => {
if (isRetainableRoute) {
window.scrollTo(0, retainedComponents.current[router.asPath].scrollPos)
}
}, [Component, pageProps])
return (
<div>
<div style={{ display: isRetainableRoute ? 'block' : 'none' }}>
{Object.entries(retainedComponents.current).map(([path, c]) => (
<div
key={path}
style={{ display: router.asPath === path ? 'block' : 'none' }}
>
{c.component}
</div>
))}
</div>
{!isRetainableRoute && <Component {...pageProps} />}
</div>
)
}
export default App
@GusRuss89
Copy link
Author

@nandorojo I'm not familiar with ScrollView but surely it has some way to get and set the scroll position? If so it should be exactly the same but with those methods instead of window.scrollY and window.scrollTo().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment