Capítulo 32 de 57

Chapter 32: Scroll Restoration

Core Idea

TanStack Router ships built-in hash/top-of-page scrolling, plus an opt-in scrollRestoration: true router option that automatically caches and restores scroll positions (including nested scrollable containers) across navigations, addressing SPA-specific challenges that native browser scroll restoration doesn't solve.

Key Concepts

  • Out-of-the-box Behavior: Hash scrolling and top-of-page scrolling on navigation work without any configuration.
  • scrollToTopSelectors: Router option listing CSS selectors (or functions returning elements, for cases document.querySelector can't reach, e.g. inside a shadow root) for additional scrollable containers to reset to top on navigation, alongside window (which is always included and can't be disabled).
  • scrollRestoration: true: Enables full scroll restoration, monitoring scroll events, registering scrollable areas, and restoring positions for each area (including window/body) before DOM paint after successful navigations, mirroring native browser back/forward scroll behavior.
  • getScrollRestorationKey: Customizes the cache key used per scrollable area/location; defaults to location.state.__TSR_key (a unique per-history-entry key). Can be overridden e.g. to key by location.pathname so identical paths always share a scroll position regardless of history entry.
  • resetScroll option: Available on <Link resetScroll={false}>, navigate({ resetScroll: false }), and redirect({ resetScroll: false }); when false, suppresses both restoring and resetting-to-top scroll behavior for that specific navigation.
  • useElementScrollRestoration + data-scroll-restoration-id: Manual scroll restoration API for cases like virtualized lists, where you need the cached scrollY (via getElement: () => window or a specific id) to seed a virtualizer's initialOffset, and tag the scrollable element with data-scroll-restoration-id so the watcher picks it up.
  • scrollRestorationBehavior: Router option controlling the scroll transition style, 'smooth' | 'instant' | 'auto' (same values as the native scrollIntoView behavior option).
  • <ScrollRestoration /> component: Still functional but deprecated in favor of the scrollRestoration: true router option.

Code Examples

const router = createRouter({
  scrollRestoration: true,
  scrollToTopSelectors: ['#main-scrollable-area'],
  scrollRestorationBehavior: 'instant',
})
  • What it demonstrates: Enabling full scroll restoration, including resetting a nested scrollable container to the top on navigation, with instant (non-smooth) transitions.

Key Takeaways

  1. scrollRestoration: true is the modern, recommended way to enable full scroll restoration; the older <ScrollRestoration /> component still works but is deprecated.
  2. For virtualized lists, native scroll restoration alone isn't enough since content height depends on the virtualizer, use useElementScrollRestoration to seed the virtualizer's initialOffset from the cached scroll position.
  3. Use resetScroll: false on a specific Link/navigate/redirect call when a navigation should neither restore nor reset scroll (e.g. updating a search param that shouldn't move the viewport).

Connects To

  • Ch 23: Navigation, the resetScroll option lives on NavigateOptions.
  • Ch 31: History Types, scroll restoration keys are derived from history entry state (__TSR_key).