Framework
Version
Integrationen

Scroll-Wiederherstellung

Hash-/Seitenanfang-Scrolling

Out of the box unterstützt TanStack Router sowohl Hash-Scrolling als auch Scrollen zum Seitenanfang ohne zusätzliche Konfiguration.

Scroll-to-top & verschachtelte scrollbare Bereiche

Standardmäßig imitiert Scrollen zum Seitenanfang das Verhalten des Browsers, was bedeutet, dass nach erfolgreicher Navigation nur das window selbst nach oben gescrollt wird. Für viele Anwendungen ist es jedoch üblich, dass der Hauptscrollbereich aufgrund fortgeschrittener Layouts ein verschachtelter div oder Ähnliches ist. Wenn Sie möchten, dass TanStack Router auch diese Hauptscrollbereiche für Sie scrollt, können Sie Selektoren hinzufügen, um sie mithilfe von routerOptions.scrollToTopSelectors anzusprechen.

tsx
const router = createRouter({
  scrollToTopSelectors: ['#main-scrollable-area'],
})
const router = createRouter({
  scrollToTopSelectors: ['#main-scrollable-area'],
})

Für komplexe Selektoren, die nicht einfach mithilfe von document.querySelector(selector) aufgelöst werden können, können Sie Funktionen übergeben, die HTML-Elemente zurückgeben, an routerOptions.scrollToTopSelectors.

tsx
const selector = () =>
  document
    .querySelector('#shadowRootParent')
    ?.shadowRoot?.querySelector('#main-scrollable-area')

const router = createRouter({
  scrollToTopSelectors: [selector],
})
const selector = () =>
  document
    .querySelector('#shadowRootParent')
    ?.shadowRoot?.querySelector('#main-scrollable-area')

const router = createRouter({
  scrollToTopSelectors: [selector],
})

Diese Selektoren werden zusätzlich zu window behandelt, was derzeit nicht deaktiviert werden kann.

Scroll-Wiederherstellung

Scroll-Wiederherstellung ist der Prozess der Wiederherstellung der Scroll-Position einer Seite, wenn der Benutzer zu ihr zurücknavigiert. Dies ist normalerweise eine integrierte Funktion für Standard-HTML-basierte Websites, kann aber für SPA-Anwendungen schwierig zu replizieren sein, da

  • SPAs verwenden typischerweise die history.pushState API für die Navigation, sodass der Browser die Scroll-Position nicht nativ wiederherstellt
  • SPAs rendern manchmal Inhalte asynchron, sodass der Browser die Höhe der Seite erst nach dem Rendern kennt
  • SPAs können manchmal verschachtelte scrollbare Container verwenden, um spezifische Layouts und Funktionen zu erzwingen.

Nicht nur das, sondern es ist sehr üblich, dass Anwendungen mehrere scrollbare Bereiche innerhalb einer App haben, nicht nur den Body. Zum Beispiel könnte eine Chat-Anwendung eine scrollbare Seitenleiste und einen scrollbaren Chat-Bereich haben. In diesem Fall möchten Sie die Scroll-Position beider Bereiche unabhängig voneinander wiederherstellen.

Um dieses Problem zu lösen, bietet TanStack Router eine Scroll-Wiederherstellungskomponente und einen Hook, die den Prozess des Überwachens, Zwischenspeicherns und Wiederherstellens von Scroll-Positionen für Sie übernehmen.

Dies geschieht durch

  • Überwachung des DOM auf Scroll-Ereignisse
  • Registrierung scrollbarer Bereiche im Scroll-Wiederherstellungs-Cache
  • Abhören der entsprechenden Router-Ereignisse, um zu wissen, wann Scroll-Positionen zwischengespeichert und wiederhergestellt werden sollen
  • Speichern von Scroll-Positionen für jeden scrollbaren Bereich im Cache (einschließlich window und body)
  • Wiederherstellung von Scroll-Positionen nach erfolgreichen Navigationen vor dem DOM-Paint

Das mag nach viel klingen, aber für Sie ist es so einfach wie das:

tsx
import { createRouter } from '@tanstack/react-router'

const router = createRouter({
  scrollRestoration: true,
})
import { createRouter } from '@tanstack/react-router'

const router = createRouter({
  scrollRestoration: true,
})

Hinweis

Die Komponente <ScrollRestoration /> funktioniert weiterhin, wurde aber als veraltet markiert.

Benutzerdefinierte Cache-Schlüssel

Angelehnt an die eigenen Scroll-Wiederherstellungs-APIs von Remix können Sie auch den Schlüssel anpassen, der zum Zwischenspeichern von Scroll-Positionen für einen bestimmten scrollbaren Bereich verwendet wird, mithilfe der getKey Option. Dies könnte beispielsweise verwendet werden, um zu erzwingen, dass dieselbe Scroll-Position verwendet wird, unabhängig von der Browserhistorie des Benutzers.

Die getKey Option empfängt den relevanten Location State von TanStack Router und erwartet, dass Sie einen String zurückgeben, um die scrollbaren Messungen für diesen State eindeutig zu identifizieren.

Der Standard- getKey ist (location) => location.state.__TSR_key!, wobei __TSR_key der eindeutige Schlüssel ist, der für jeden Eintrag im Verlauf generiert wird.

Ältere Versionen vor v1.121.34 verwendeten state.key als Standard-Schlüssel, aber dies wurde zugunsten von state.__TSR_key als veraltet markiert. Vorerst ist location.state.key noch für die Kompatibilität verfügbar, wird aber in der nächsten Hauptversion entfernt.

Beispiele

Sie könnten das Scrolling mit dem Pfad synchronisieren

tsx
import { createRouter } from '@tanstack/react-router'

const router = createRouter({
  getScrollRestorationKey: (location) => location.pathname,
})
import { createRouter } from '@tanstack/react-router'

const router = createRouter({
  getScrollRestorationKey: (location) => location.pathname,
})

Sie können Pfade bedingt synchronisieren und für den Rest den Schlüssel verwenden

tsx
import { createRouter } from '@tanstack/react-router'

const router = createRouter({
  getScrollRestorationKey: (location) => {
    const paths = ['/', '/chat']
    return paths.includes(location.pathname)
      ? location.pathname
      : location.state.__TSR_key!
  },
})
import { createRouter } from '@tanstack/react-router'

const router = createRouter({
  getScrollRestorationKey: (location) => {
    const paths = ['/', '/chat']
    return paths.includes(location.pathname)
      ? location.pathname
      : location.state.__TSR_key!
  },
})

Scroll-Wiederherstellung verhindern

Manchmal möchten Sie möglicherweise verhindern, dass die Scroll-Wiederherstellung stattfindet. Um dies zu tun, können Sie die Option resetScroll nutzen, die für die folgenden APIs verfügbar ist:

  • <Link resetScroll={false}>
  • navigate({ resetScroll: false })
  • redirect({ resetScroll: false })

Wenn resetScroll auf false gesetzt ist, wird die Scroll-Position für die nächste Navigation nicht wiederhergestellt (wenn zu einem vorhandenen Verlaufseintrag im Stack navigiert wird) oder auf oben zurückgesetzt (wenn es sich um einen neuen Verlaufseintrag im Stack handelt).

Manuelle Scroll-Wiederherstellung

Meistens müssen Sie nichts Besonderes tun, damit die Scroll-Wiederherstellung funktioniert. Es gibt jedoch einige Fälle, in denen Sie die Scroll-Wiederherstellung manuell steuern müssen. Das häufigste Beispiel sind virtualisierte Listen.

Um die Scroll-Wiederherstellung für virtualisierte Listen im gesamten Browserfenster manuell zu steuern

tsx
function Component() {
  const scrollEntry = useElementScrollRestoration({
    getElement: () => window,
  })

  // Let's use TanStack Virtual to virtualize some content!
  const virtualizer = useWindowVirtualizer({
    count: 10000,
    estimateSize: () => 100,
    // We pass the scrollY from the scroll restoration entry to the virtualizer
    // as the initial offset
    initialOffset: scrollEntry?.scrollY,
  })

  return (
    <div>
      {virtualizer.getVirtualItems().map(item => (
        ...
      ))}
    </div>
  )
}
function Component() {
  const scrollEntry = useElementScrollRestoration({
    getElement: () => window,
  })

  // Let's use TanStack Virtual to virtualize some content!
  const virtualizer = useWindowVirtualizer({
    count: 10000,
    estimateSize: () => 100,
    // We pass the scrollY from the scroll restoration entry to the virtualizer
    // as the initial offset
    initialOffset: scrollEntry?.scrollY,
  })

  return (
    <div>
      {virtualizer.getVirtualItems().map(item => (
        ...
      ))}
    </div>
  )
}

Um die Scroll-Wiederherstellung für ein bestimmtes Element manuell zu steuern, können Sie den Hook useElementScrollRestoration und das DOM-Attribut data-scroll-restoration-id verwenden.

tsx
function Component() {
  // We need a unique ID for manual scroll restoration on a specific element
  // It should be as unique as possible for this element across your app
  const scrollRestorationId = 'myVirtualizedContent'

  // We use that ID to get the scroll entry for this element
  const scrollEntry = useElementScrollRestoration({
    id: scrollRestorationId,
  })

  // Let's use TanStack Virtual to virtualize some content!
  const virtualizerParentRef = React.useRef<HTMLDivElement>(null)
  const virtualizer = useVirtualizer({
    count: 10000,
    getScrollElement: () => virtualizerParentRef.current,
    estimateSize: () => 100,
    // We pass the scrollY from the scroll restoration entry to the virtualizer
    // as the initial offset
    initialOffset: scrollEntry?.scrollY,
  })

  return (
    <div
      ref={virtualizerParentRef}
      // We pass the scroll restoration ID to the element
      // as a custom attribute that will get picked up by the
      // scroll restoration watcher
      data-scroll-restoration-id={scrollRestorationId}
      className="flex-1 border rounded-lg overflow-auto relative"
    >
      ...
    </div>
  )
}
function Component() {
  // We need a unique ID for manual scroll restoration on a specific element
  // It should be as unique as possible for this element across your app
  const scrollRestorationId = 'myVirtualizedContent'

  // We use that ID to get the scroll entry for this element
  const scrollEntry = useElementScrollRestoration({
    id: scrollRestorationId,
  })

  // Let's use TanStack Virtual to virtualize some content!
  const virtualizerParentRef = React.useRef<HTMLDivElement>(null)
  const virtualizer = useVirtualizer({
    count: 10000,
    getScrollElement: () => virtualizerParentRef.current,
    estimateSize: () => 100,
    // We pass the scrollY from the scroll restoration entry to the virtualizer
    // as the initial offset
    initialOffset: scrollEntry?.scrollY,
  })

  return (
    <div
      ref={virtualizerParentRef}
      // We pass the scroll restoration ID to the element
      // as a custom attribute that will get picked up by the
      // scroll restoration watcher
      data-scroll-restoration-id={scrollRestorationId}
      className="flex-1 border rounded-lg overflow-auto relative"
    >
      ...
    </div>
  )
}

Scroll-Verhalten

Um das Scroll-Verhalten beim Navigieren zwischen Seiten zu steuern, können Sie die Option scrollRestorationBehavior verwenden. Dies ermöglicht es Ihnen, den Übergang zwischen Seiten sofort anstelle eines sanften Scrolls zu gestalten. Die globale Konfiguration des Scroll-Wiederherstellungsverhaltens hat dieselben Optionen wie die vom Browser unterstützten, nämlich smooth, instant und auto (siehe MDN für weitere Informationen).

tsx
import { createRouter } from '@tanstack/react-router'

const router = createRouter({
  scrollRestorationBehavior: 'instant',
})
import { createRouter } from '@tanstack/react-router'

const router = createRouter({
  scrollRestorationBehavior: 'instant',
})
Unsere Partner
Code Rabbit
Netlify
Neon
Clerk
Convex
Sentry
Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.

Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.