1.0.0 • Published 1 year ago

@lonli-lokli/scroll-restoration v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

React Scroll Restoration

A lightweight, framework-agnostic scroll restoration solution for React applications. This library helps preserve and restore scroll positions when navigating between pages, providing a smoother user experience.

Features

  • 🔄 Restore scroll positions when navigating back and forth
  • 📦 No router dependencies
  • 🧩 Compatible with any React routing solution
  • 📱 Works with nested scrollable elements
  • 🔍 Supports custom location key strategies
  • 🌊 Configurable scroll behavior
  • 🔌 Extensible navigation detection

Installation

npm install react-scroll-restoration
# or
yarn add react-scroll-restoration
# or
pnpm add react-scroll-restoration

Basic Usage

import { ScrollRestoration } from 'react-scroll-restoration';

function App() {
  return (
    <>
      <ScrollRestoration />
      {/* Your application content */}
    </>
  );
}

Advanced Usage

Custom Configuration

import { ScrollRestoration } from 'react-scroll-restoration';

function App() {
  return (
    <>
      <ScrollRestoration 
        // Use only pathname for identifying routes
        getKey={(location) => location.pathname}
        // Enable smooth scrolling
        scrollBehavior="smooth"
      />
      {/* Your application content */}
    </>
  );
}

With React Router

import { ScrollRestoration } from 'react-scroll-restoration';
import { useLocation, useNavigate } from 'react-router-dom';

function App() {
  const location = useLocation();
  
  return (
    <>
      <ScrollRestoration 
        // Use React Router's location
        getCurrentLocation={() => ({
          href: window.location.href,
          pathname: location.pathname,
          search: location.search,
          hash: location.hash,
          state: location.state,
        })}
        // Listen for React Router navigation
        navigationListener={(onNavigate) => {
          const unlisten = history.listen(() => {
            onNavigate(location);
          });
          return unlisten;
        }}
      />
      {/* Your application content */}
    </>
  );
}

With Next.js

import { ScrollRestoration } from 'react-scroll-restoration';
import { useRouter } from 'next/router';

function MyApp({ Component, pageProps }) {
  const router = useRouter();
  
  return (
    <>
      <ScrollRestoration 
        getKey={(location) => location.pathname}
        navigationListener={(onNavigate) => {
          const handleRouteChange = () => {
            onNavigate({
              pathname: router.pathname,
              search: router.query ? Object.entries(router.query)
                .map(([key, value]) => `${key}=${value}`)
                .join('&') : '',
              hash: window.location.hash,
              href: window.location.href,
              state: history.state,
            });
          };
          
          router.events.on('routeChangeComplete', handleRouteChange);
          
          return () => {
            router.events.off('routeChangeComplete', handleRouteChange);
          };
        }}
      />
      <Component {...pageProps} />
    </>
  );
}

export default MyApp;

Scrollable Elements

Using data attribute (recommended)

function LongList() {
  return (
    <div 
      className="overflow-auto h-80"
      data-scroll-restoration-id="user-comments"
    >
      {/* Long list content */}
    </div>
  );
}

Using imperative handle

import { useRef, useEffect } from 'react';
import { useElementScrollRestoration } from 'react-scroll-restoration';

function LongList() {
  const containerRef = useRef<HTMLDivElement>(null);
  
  // Get stored scroll position
  const scrollPosition = useElementScrollRestoration({
    getElement: () => containerRef.current,
  });
  
  // Apply stored scroll position on mount
  useEffect(() => {
    if (containerRef.current && scrollPosition) {
      containerRef.current.scrollLeft = scrollPosition.scrollX;
      containerRef.current.scrollTop = scrollPosition.scrollY;
    }
  }, [scrollPosition]);
  
  return (
    <div 
      ref={containerRef}
      className="overflow-auto h-80"
    >
      {/* Long list content */}
    </div>
  );
}

API Reference

useScrollRestoration(options?)

The main hook for enabling scroll restoration.

Options

OptionTypeDescription
getKey(location: Location) => stringFunction to generate a unique key for a location
scrollBehavior'auto' \| 'smooth'Scroll behavior when restoring position
getCurrentLocation() => LocationFunction to get current location
navigationListener(onNavigate: (location: Location) => void) => () => voidFunction to listen for location changes

ScrollRestoration Component

A component wrapper for useScrollRestoration that returns null.

<ScrollRestoration
  getKey={(location) => location.pathname}
  scrollBehavior="smooth"
/>

useElementScrollRestoration(options)

A hook for retrieving stored scroll positions for specific elements.

Options

OptionTypeDescription
idstringID to use with data-scroll-restoration-id attribute
getElement() => Element \| null \| undefinedFunction to get the element reference
getKey(location: Location) => stringFunction to generate a unique key for a location
getCurrentLocation() => LocationFunction to get current location

Browser Support

The library works in all modern browsers that support these APIs:

  • sessionStorage
  • window.history
  • MutationObserver

TypeScript Support

This library is written in TypeScript and provides type definitions out of the box.

License

MIT

1.0.0

1 year ago

0.14.0

1 year ago

0.12.0

1 year ago

0.13.0

1 year ago

0.11.0-0

1 year ago

0.11.0

1 year ago

0.10.0

1 year ago

0.8.0

1 year ago

0.7.0

1 year ago

0.6.0

1 year ago

0.5.0

1 year ago

0.4.0

1 year ago

0.3.0

1 year ago