Skip to content

Instantly share code, notes, and snippets.

@claus
Created May 14, 2020 05:35
Show Gist options
  • Select an option

  • Save claus/992a5596d6532ac91b24abe24e10ae81 to your computer and use it in GitHub Desktop.

Select an option

Save claus/992a5596d6532ac91b24abe24e10ae81 to your computer and use it in GitHub Desktop.

Revisions

  1. claus created this gist May 14, 2020.
    8 changes: 8 additions & 0 deletions _app.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    import useScrollRestoration from "utils/hooks/useScrollRestoration";

    const App = ({ Component, pageProps, router }) => {
    useScrollRestoration(router);
    return <Component {...pageProps} />;
    };

    export default App;
    56 changes: 56 additions & 0 deletions useScrollRestoration.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,56 @@
    import { useEffect } from 'react';

    import Router from 'next/router';

    function saveScrollPos(url) {
    const scrollPos = { x: window.scrollX, y: window.scrollY };
    sessionStorage.setItem(url, JSON.stringify(scrollPos));
    }

    function restoreScrollPos(url) {
    const scrollPos = JSON.parse(sessionStorage.getItem(url));
    if (scrollPos) {
    window.scrollTo(scrollPos.x, scrollPos.y);
    }
    }

    export default function useScrollRestoration(router) {
    useEffect(() => {
    if ('scrollRestoration' in window.history) {
    let shouldScrollRestore = false;
    window.history.scrollRestoration = 'manual';
    restoreScrollPos(router.asPath);

    const onBeforeUnload = event => {
    saveScrollPos(router.asPath);
    delete event['returnValue'];
    };

    const onRouteChangeStart = () => {
    saveScrollPos(router.asPath);
    };

    const onRouteChangeComplete = url => {
    if (shouldScrollRestore) {
    shouldScrollRestore = false;
    restoreScrollPos(url);
    }
    };

    window.addEventListener('beforeunload', onBeforeUnload);
    Router.events.on('routeChangeStart', onRouteChangeStart);
    Router.events.on('routeChangeComplete', onRouteChangeComplete);
    Router.beforePopState(() => {
    shouldScrollRestore = true;
    return true;
    });

    return () => {
    window.removeEventListener('beforeunload', onBeforeUnload);
    Router.events.off('routeChangeStart', onRouteChangeStart);
    Router.events.off('routeChangeComplete', onRouteChangeComplete);
    Router.beforePopState(() => true);
    };
    }
    }, [router]);
    }