nextjs scrollRestoration


  • administrators

    By default nextjs auto scroll to the top when the router changes. Most of time, this what we wanted, but sometimes, we would like scroll could be restored, especially, user uses "Back" or "Forward" navigation.
    Here is my way:

    1. set scrollRestoration to true. in next.config.js
    2. use javascript to scroll to the top when the page is newly loaded
     isNavigation = false;
    
      handleRouteChange = (url) => {
        console.log("User navigated to:", url);
        gtag.pageview(url);
        
        if (!this.isNavigation) {
          console.log("scroll to top when load a new page");
          // console.log("URL", url);
          this.timerHandle = setTimeout(() => {
            window.scrollTo(0, 0);
            this.timerHandle = 0;
          }, 100);
    
          this.isNavigation = false;
        }
    
        NProgress.done();
      };
    
      handleBeforePopState = ({ url, as, options }) => {
        console.log("User navigated backwards or forwards");
        this.isNavigation = true;
        // Do something when user navigates back or forward
        return true;
      };
    
      handleStart = (url) => {
        // console.log(`Loading: ${url}`);
        NProgress.start();
      };
      handleStop = () => {
        NProgress.done();
      };
    
    componentDidMount = async () => {
        Router.events.on("routeChangeComplete", this.handleRouteChange);
        Router.events.on("routeChangeStart", this.handleStart);
        Router.events.on("routeChangeError", this.handleStop);
        Router.beforePopState(this.handleBeforePopState);
      };
    
      componentWillUnmount = () => {
        Router.events.off("routeChangeComplete", this.handleRouteChange);
        Router.events.off("routeChangeStart", this.handleStart);
        Router.events.off("routeChangeError", this.handleStop);
        Router.beforePopState(() => true);
        if (this.timerHandle) {
          // Yes, clear it
          clearTimeout(this.timerHandle);
          this.timerHandle = 0;
        }
      };