Blog>
Snippets

Integrating Scroll Restoration with Page Transitions

Illustrate how to synchronize scroll restoration with custom page transition animations using TanStack Router, ensuring a seamless user experience.
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

function useScrollRestoration(router) {
  useEffect(() => {
    const handleRouteChange = () => {
      const savedPosition = sessionStorage.getItem(router.location.pathname);
      if (savedPosition) {
        window.scrollTo({
          top: parseInt(savedPosition, 10),
          behavior: 'smooth'
        });
      }
    };

    router.listen(handleRouteChange);
    return () => router.unlisten(handleRouteChange);
  }, [router]);
}
This code sets up scroll restoration with smooth scrolling for page transitions in a SPA using TanStack Router. It listens for route changes, retrieves the saved scroll position from sessionStorage, and applies it with a smooth scroll behavior.
import { useLayoutEffect } from 'react';

function useSaveScrollPosition(router) {
  useLayoutEffect(() => {
    const saveScrollPosition = () => sessionStorage.setItem(router.location.pathname, window.scrollY.toString());

    window.addEventListener('beforeunload', saveScrollPosition);
    return () => window.removeEventListener('beforeunload', saveScrollPosition);
  }, [router]);
}
This code snippet handles saving the current scroll position to sessionStorage when the user navigates away from the current route. It ensures that the scroll position of each page is preserved before unloading.
async function waitForContentAndRestoreScroll(router) {
  await new Promise(resolve => setTimeout(resolve, 500)); // Simulation of content loading
  const savedPosition = sessionStorage.getItem(router.location.pathname);
  if (savedPosition) {
    window.scrollTo({
      top: parseInt(savedPosition, 10),
      behavior: 'smooth'
    });
  }
}
This asynchronous function simulates waiting for content to load (e.g., fetching data) before restoring the scroll position. It uses a hardcoded delay as a placeholder for dynamic content loading logic.