Capítulo 15 de 24
Scroll restoration remembers and reapplies scroll position per route (and per scrollable element) as the user navigates back and forth, so long lists don't reset to the top on every visit. TanStack Router handles this automatically at the window level via a router option, and offers useElementScrollRestoration plus a data attribute for restoring scroll inside specific inner containers (e.g. a virtualized list).
createRoute / createRootRoute / createRouter)@tanstack/react-router (useElementScrollRestoration), @tanstack/react-virtual (for the virtualized panel), @tanstack/react-router-devtoolssrc/main.tsx with three routes (/, /about, /by-element), each rendering a tall list of items so scroll position is observable; /by-element also renders a virtualized panel to demonstrate element-scoped restoration.const router = createRouter({
routeTree,
defaultPreload: 'intent',
scrollRestoration: true,
})
Opting a specific Link out of the default scroll-to-top behavior:
<Link to="/about" resetScroll={false}>
About (No Reset)
</Link>
Restoring scroll inside one scrollable element (used with a virtualizer's initialOffset):
const scrollRestorationId = 'myVirtualizedContent'
const scrollEntry = useElementScrollRestoration({ id: scrollRestorationId })
const virtualizer = useVirtualizer({
count: 10000,
getScrollElement: () => virtualizerParentRef.current,
estimateSize: () => 100,
initialOffset: scrollEntry?.scrollY,
})
// ...
<div
ref={virtualizerParentRef}
data-scroll-restoration-id={scrollRestorationId}
className="flex-1 border rounded-lg overflow-auto relative"
>
scrollRestoration: true on createRouter covers window scroll automatically; per-element restoration requires a stable data-scroll-restoration-id attribute on the scrollable node plus useElementScrollRestoration({ id }) to read back the saved offset for consumers like a virtualizer.scrollRestoration: true once at the router level; it covers window-level scroll for every route with no per-route code.resetScroll={false} on a Link when navigating within the same conceptual view should preserve scroll instead of jumping to top (the default on route change).overflow-auto), tag the element with data-scroll-restoration-id and read its saved position with useElementScrollRestoration({ id }); feed that into the scrolling library's initial offset.loader functions) let the router wait for data before restoring scroll, avoiding a restore-then-jump flash on slow-loading routes.