loadersloader-Parameterloaders konsumierenloaderDeps zum Zugriff auf SuchparameterstaleTime zur Steuerung, wie lange Daten als frisch geltenshouldReload und gcTime zur Deaktivierung des CachingsrouteOptions.loaderDepspreload-FlagsrouteOptions.onErrorrouteOptions.onCatchrouteOptions.errorComponentErrorComponentDas Laden von Daten ist eine häufige Anforderung für Webanwendungen und steht im Zusammenhang mit dem Routing. Beim Laden einer Seite für Ihre App ist es ideal, wenn alle asynchronen Anforderungen der Seite so früh wie möglich und parallel abgerufen und erfüllt werden. Der Router ist der beste Ort, um diese asynchronen Abhängigkeiten zu koordinieren, da er normalerweise der einzige Ort in Ihrer App ist, der weiß, wohin sich Benutzer bewegen, bevor Inhalte gerendert werden.
Möglicherweise sind Sie mit getServerSideProps aus Next.js oder loadern aus Remix/React-Router vertraut. TanStack Router bietet ähnliche Funktionen zum Vorabladen/Laden von Assets pro Route parallel, wodurch eine so schnelle Anzeige wie möglich erreicht wird, während Daten abgerufen werden.
Über diese normalen Erwartungen an einen Router hinaus geht TanStack Router noch einen Schritt weiter und bietet **integriertes SWR-Caching**, eine langfristige In-Memory-Caching-Schicht für Routen-Loader. Das bedeutet, dass Sie TanStack Router verwenden können, um Daten für Ihre Routen vorab zu laden, damit sie sofort geladen werden, oder um Routendaten für zuvor besuchte Routen temporär zu cachen, um sie später wiederzuverwenden.
Jedes Mal, wenn eine URL/Historienaktualisierung erkannt wird, führt der Router die folgende Sequenz aus
Es ist sehr wahrscheinlich, dass der Router-Cache von TanStack gut für die meisten kleineren bis mittleren Anwendungen geeignet ist, aber es ist wichtig, die Kompromisse zu verstehen, wenn man ihn gegenüber einer robusteren Caching-Lösung wie TanStack Query verwendet.
Vorteile des TanStack Router-Caches
Nachteile des TanStack Router-Caches
Tipp
Wenn Sie sofort wissen, dass Sie etwas Robusteres wie TanStack Query verwenden möchten oder müssen, springen Sie zum Leitfaden External Data Loading.
Der Router-Cache ist integriert und so einfach, dass Sie Daten aus der loader-Funktion jeder Route zurückgeben. Lassen Sie uns lernen, wie!
Routen- loader-Funktionen werden aufgerufen, wenn ein Routen-Match geladen wird. Sie werden mit einem einzigen Parameter aufgerufen, einem Objekt, das viele hilfreiche Eigenschaften enthält. Wir werden diese kurz behandeln, aber zuerst schauen wir uns ein Beispiel für eine Routen- loader-Funktion an.
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
})
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
})
Die loader-Funktion empfängt ein einzelnes Objekt mit den folgenden Eigenschaften
Mit diesen Parametern können wir viele coole Dinge tun, aber schauen wir uns zuerst an, wie wir sie steuern können und wann die loader-Funktion aufgerufen wird.
Um Daten aus einem loader zu konsumieren, verwenden Sie den Hook useLoaderData, der auf Ihrem Route-Objekt definiert ist.
const posts = Route.useLoaderData()
const posts = Route.useLoaderData()
Wenn Sie keinen direkten Zugriff auf Ihr Routenobjekt haben (d. h. Sie befinden sich tief im Komponentendbaum der aktuellen Route), können Sie getRouteApi verwenden, um auf denselben Hook (sowie die anderen Hooks des Route-Objekts) zuzugreifen. Dies sollte dem Importieren des Route-Objekts vorgezogen werden, was wahrscheinlich zu zirkulären Abhängigkeiten führen würde.
import { getRouteApi } from '@tanstack/react-router'
// in your component
const routeApi = getRouteApi('/posts')
const data = routeApi.useLoaderData()
import { getRouteApi } from '@tanstack/react-router'
// in your component
const routeApi = getRouteApi('/posts')
const data = routeApi.useLoaderData()
TanStack Router bietet eine integrierte Stale-While-Revalidate-Caching-Schicht für Routen-Loader, die auf den Abhängigkeiten einer Route basiert
Mit diesen Abhängigkeiten als Schlüssel speichert TanStack Router die von der loader-Funktion einer Route zurückgegebenen Daten und verwendet sie zur Erfüllung nachfolgender Anfragen für denselben Routen-Match. Das bedeutet, wenn die Daten einer Route bereits im Cache vorhanden sind, werden sie sofort zurückgegeben, dann **möglicherweise** im Hintergrund erneut abgerufen, abhängig von der "Aktualität" der Daten.
Um Routenabhängigkeiten und "Aktualität" zu steuern, bietet TanStack Router eine Fülle von Optionen zur Steuerung des Schlüssel- und Caching-Verhaltens Ihrer Routen-Loader. Schauen wir uns diese in der Reihenfolge an, in der Sie sie am wahrscheinlichsten verwenden werden.
Stellen Sie sich vor, eine /posts-Route unterstützt eine Paginierung über die Suchparameter offset und limit. Damit der Cache diese Daten eindeutig speichern kann, müssen wir über die loaderDeps-Funktion auf diese Suchparameter zugreifen. Indem wir sie explizit identifizieren, werden die einzelnen Routen-Matches für /posts mit unterschiedlichen offset und limit nicht vermischt!
Sobald wir diese Abhängigkeiten eingerichtet haben, wird die Route bei Änderungen der Abhängigkeiten immer neu geladen.
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
loaderDeps: ({ search: { offset, limit } }) => ({ offset, limit }),
loader: ({ deps: { offset, limit } }) =>
fetchPosts({
offset,
limit,
}),
})
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
loaderDeps: ({ search: { offset, limit } }) => ({ offset, limit }),
loader: ({ deps: { offset, limit } }) =>
fetchPosts({
offset,
limit,
}),
})
Standardmäßig ist die staleTime für Navigationen auf 0 ms (und 30 Sekunden für Vorabladungen) gesetzt, was bedeutet, dass die Daten der Route immer als veraltet gelten und immer im Hintergrund neu geladen werden, wenn die Route übereinstimmt und zu ihr navigiert wird.
Dies ist eine gute Standardeinstellung für die meisten Anwendungsfälle, aber Sie werden feststellen, dass einige Routendaten statischer oder potenziell teuer im Laden sind. In diesen Fällen können Sie die Option staleTime verwenden, um zu steuern, wie lange die Daten der Route für Navigationen als frisch gelten. Schauen wir uns ein Beispiel an.
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
// Consider the route's data fresh for 10 seconds
staleTime: 10_000,
})
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
// Consider the route's data fresh for 10 seconds
staleTime: 10_000,
})
Durch die Übergabe von 10_000 an die Option staleTime teilen wir dem Router mit, die Daten der Route für 10 Sekunden als frisch zu betrachten. Das bedeutet, wenn der Benutzer innerhalb von 10 Sekunden nach dem letzten Loader-Ergebnis von /about zu /posts navigiert, werden die Daten der Route nicht neu geladen. Wenn der Benutzer dann nach 10 Sekunden von /about zu /posts navigiert, werden die Daten der Route **im Hintergrund** neu geladen.
Um das Stale-While-Revalidate-Caching für eine Route zu deaktivieren, setzen Sie die Option staleTime auf Infinity.
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
staleTime: Infinity,
})
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
staleTime: Infinity,
})
Sie können dies sogar für alle Routen deaktivieren, indem Sie die Option defaultStaleTime auf dem Router setzen.
const router = createRouter({
routeTree,
defaultStaleTime: Infinity,
})
const router = createRouter({
routeTree,
defaultStaleTime: Infinity,
})
Ähnlich wie bei der Standardfunktionalität von Remix möchten Sie möglicherweise eine Route so konfigurieren, dass sie nur beim Eintritt oder bei Änderung kritischer Loader-Abhängigkeiten geladen wird. Dies können Sie mit der Option gcTime in Kombination mit der Option shouldReload erreichen, die entweder einen boolean oder eine Funktion akzeptiert, die dieselben beforeLoad- und loaderContext-Parameter empfängt und einen booleschen Wert zurückgibt, der angibt, ob die Route neu geladen werden soll.
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
loaderDeps: ({ search: { offset, limit } }) => ({ offset, limit }),
loader: ({ deps }) => fetchPosts(deps),
// Do not cache this route's data after it's unloaded
gcTime: 0,
// Only reload the route when the user navigates to it or when deps change
shouldReload: false,
})
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
loaderDeps: ({ search: { offset, limit } }) => ({ offset, limit }),
loader: ({ deps }) => fetchPosts(deps),
// Do not cache this route's data after it's unloaded
gcTime: 0,
// Only reload the route when the user navigates to it or when deps change
shouldReload: false,
})
Auch wenn Sie kurzfristiges Caching für Ihre Routendaten deaktivieren, können Sie dennoch von der Vorabladung profitieren! Mit der obigen Konfiguration funktioniert die Vorabladung weiterhin "einfach" mit der Standard- preloadGcTime. Das bedeutet, wenn eine Route vorab geladen und dann navigiert wird, gelten die Daten der Route als frisch und werden nicht neu geladen.
Um die Vorabladung zu deaktivieren, schalten Sie sie nicht über die Optionen routerOptions.defaultPreload oder routeOptions.preload ein.
Wir behandeln diesen Anwendungsfall auf der Seite External Data Loading, aber wenn Sie einen externen Cache wie TanStack Query verwenden möchten, können Sie dies tun, indem Sie alle Loader-Events an Ihren externen Cache übergeben. Solange Sie die Standardeinstellungen verwenden, besteht die einzige Änderung, die Sie vornehmen müssen, darin, die Option defaultPreloadStaleTime für den Router auf 0 zu setzen.
const router = createRouter({
routeTree,
defaultPreloadStaleTime: 0,
})
const router = createRouter({
routeTree,
defaultPreloadStaleTime: 0,
})
Dies stellt sicher, dass jedes Vorablade-, Lade- und Neu-Lade-Ereignis Ihre loader-Funktionen auslöst, die dann von Ihrem externen Cache verarbeitet und dedupliziert werden können.
Das context-Argument, das an die loader-Funktion übergeben wird, ist ein Objekt, das eine zusammengeführte Vereinigung von Folgendem enthält.
Ganz oben im Router können Sie einen anfänglichen Kontext an den Router über die Option context übergeben. Dieser Kontext ist für alle Routen im Router verfügbar und wird von jeder Route kopiert und erweitert, wenn sie übereinstimmt. Dies geschieht durch Übergabe eines Kontexts an eine Route über die Option beforeLoad. Dieser Kontext ist für alle untergeordneten Routen der Route verfügbar. Der resultierende Kontext ist für die loader-Funktion der Route verfügbar.
In diesem Beispiel erstellen wir eine Funktion in unserem Routenkontext zum Abrufen von Beiträgen und verwenden sie dann in unserer loader-Funktion.
🧠 Kontext ist ein mächtiges Werkzeug für Dependency Injection. Sie können ihn verwenden, um Dienste, Hooks und andere Objekte in Ihren Router und Ihre Routen zu injizieren. Sie können auch Daten mit der Option beforeLoad jeder Route additiv nach unten durch den Routenbaum übergeben.
export const fetchPosts = async () => {
const res = await fetch(`/api/posts?page=${pageIndex}`)
if (!res.ok) throw new Error('Failed to fetch posts')
return res.json()
}
export const fetchPosts = async () => {
const res = await fetch(`/api/posts?page=${pageIndex}`)
if (!res.ok) throw new Error('Failed to fetch posts')
return res.json()
}
import { createRootRouteWithContext } from '@tanstack/react-router'
// Create a root route using the createRootRouteWithContext<{...}>() function and pass it whatever types you would like to be available in your router context.
export const Route = createRootRouteWithContext<{
fetchPosts: typeof fetchPosts
}>()() // NOTE: the double call is on purpose, since createRootRouteWithContext is a factory ;)
import { createRootRouteWithContext } from '@tanstack/react-router'
// Create a root route using the createRootRouteWithContext<{...}>() function and pass it whatever types you would like to be available in your router context.
export const Route = createRootRouteWithContext<{
fetchPosts: typeof fetchPosts
}>()() // NOTE: the double call is on purpose, since createRootRouteWithContext is a factory ;)
import { createFileRoute } from '@tanstack/react-router'
// Notice how our postsRoute references context to get our fetchPosts function
// This can be a powerful tool for dependency injection across your router
// and routes.
export const Route = createFileRoute('/posts')({
loader: ({ context: { fetchPosts } }) => fetchPosts(),
})
import { createFileRoute } from '@tanstack/react-router'
// Notice how our postsRoute references context to get our fetchPosts function
// This can be a powerful tool for dependency injection across your router
// and routes.
export const Route = createFileRoute('/posts')({
loader: ({ context: { fetchPosts } }) => fetchPosts(),
})
import { routeTree } from './routeTree.gen'
// Use your routerContext to create a new router
// This will require that you fullfil the type requirements of the routerContext
const router = createRouter({
routeTree,
context: {
// Supply the fetchPosts function to the router context
fetchPosts,
},
})
import { routeTree } from './routeTree.gen'
// Use your routerContext to create a new router
// This will require that you fullfil the type requirements of the routerContext
const router = createRouter({
routeTree,
context: {
// Supply the fetchPosts function to the router context
fetchPosts,
},
})
Um Pfadparameter in Ihrer loader-Funktion zu verwenden, greifen Sie über die Eigenschaft params auf die Parameter der Funktion zu. Hier ist ein Beispiel.
// routes/posts.$postId.tsx
export const Route = createFileRoute('/posts/$postId')({
loader: ({ params: { postId } }) => fetchPostById(postId),
})
// routes/posts.$postId.tsx
export const Route = createFileRoute('/posts/$postId')({
loader: ({ params: { postId } }) => fetchPostById(postId),
})
Das Übergeben eines globalen Kontexts an Ihren Router ist großartig, aber was ist, wenn Sie einen Kontext bereitstellen möchten, der spezifisch für eine Route ist? Hier kommt die Option beforeLoad ins Spiel. Die Option beforeLoad ist eine Funktion, die kurz vor dem Versuch, eine Route zu laden, ausgeführt wird und dieselben Parameter wie loader empfängt. Neben ihrer Fähigkeit, potenzielle Übereinstimmungen umzuleiten, Loader-Anfragen zu blockieren usw., kann sie auch ein Objekt zurückgeben, das in den Kontext der Route zusammengeführt wird. Schauen wir uns ein Beispiel an, in dem wir einige Daten über die Option beforeLoad in unseren Routenkontext einfügen.
// /routes/posts.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts')({
// Pass the fetchPosts function to the route context
beforeLoad: () => ({
fetchPosts: () => console.info('foo'),
}),
loader: ({ context: { fetchPosts } }) => {
console.info(fetchPosts()) // 'foo'
// ...
},
})
// /routes/posts.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts')({
// Pass the fetchPosts function to the route context
beforeLoad: () => ({
fetchPosts: () => console.info('foo'),
}),
loader: ({ context: { fetchPosts } }) => {
console.info(fetchPosts()) // 'foo'
// ...
},
})
❓ Aber Moment mal, Tanner... wo zum Teufel sind meine Suchparameter?!
Sie fragen sich vielleicht, warum search nicht direkt in den Parametern der loader-Funktion verfügbar ist. Wir haben es absichtlich so gestaltet, um Ihnen zum Erfolg zu verhelfen. Lassen Sie uns sehen, warum.
// /routes/users.user.tsx
export const Route = createFileRoute('/users/user')({
validateSearch: (search) =>
search as {
userId: string
},
loaderDeps: ({ search: { userId } }) => ({
userId,
}),
loader: async ({ deps: { userId } }) => getUser(userId),
})
// /routes/users.user.tsx
export const Route = createFileRoute('/users/user')({
validateSearch: (search) =>
search as {
userId: string
},
loaderDeps: ({ search: { userId } }) => ({
userId,
}),
loader: async ({ deps: { userId } }) => getUser(userId),
})
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
// Use zod to validate and parse the search params
validateSearch: z.object({
offset: z.number().int().nonnegative().catch(0),
}),
// Pass the offset to your loader deps via the loaderDeps function
loaderDeps: ({ search: { offset } }) => ({ offset }),
// Use the offset from context in the loader function
loader: async ({ deps: { offset } }) =>
fetchPosts({
offset,
}),
})
// /routes/posts.tsx
export const Route = createFileRoute('/posts')({
// Use zod to validate and parse the search params
validateSearch: z.object({
offset: z.number().int().nonnegative().catch(0),
}),
// Pass the offset to your loader deps via the loaderDeps function
loaderDeps: ({ search: { offset } }) => ({ offset }),
// Use the offset from context in the loader function
loader: async ({ deps: { offset } }) =>
fetchPosts({
offset,
}),
})
Die Eigenschaft abortController der loader-Funktion ist ein AbortController. Sein Signal wird abgebrochen, wenn die Route entladen wird oder wenn der loader-Aufruf veraltet ist. Dies ist nützlich, um Netzwerkanfragen abzubrechen, wenn die Route entladen wird oder wenn sich die Parameter der Route ändern. Hier ist ein Beispiel, das es mit einem Fetch-Aufruf verwendet.
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: ({ abortController }) =>
fetchPosts({
// Pass this to an underlying fetch call or anything that supports signals
signal: abortController.signal,
}),
})
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: ({ abortController }) =>
fetchPosts({
// Pass this to an underlying fetch call or anything that supports signals
signal: abortController.signal,
}),
})
Die Eigenschaft preload der loader-Funktion ist ein boolescher Wert, der true ist, wenn die Route anstelle des Ladens vorab geladen wird. Einige Datenladebibliotheken verarbeiten die Vorabladung möglicherweise anders als ein Standard-Fetch, sodass Sie preload an Ihre Datenladebibliothek übergeben oder sie verwenden, um die entsprechende Datenlade-Logik auszuführen.
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: async ({ preload }) =>
fetchPosts({
maxAge: preload ? 10_000 : 0, // Preloads should hang around a bit longer
}),
})
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: async ({ preload }) =>
fetchPosts({
maxAge: preload ? 10_000 : 0, // Preloads should hang around a bit longer
}),
})
Idealerweise können die meisten Routen-Loader ihre Daten innerhalb eines kurzen Moments auflösen, wodurch die Notwendigkeit entfällt, einen Platzhalter-Spinner anzuzeigen, und sich einfach auf Suspense verlassen, um die nächste Route zu rendern, wenn sie vollständig bereit ist. Wenn jedoch kritische Daten, die zum Rendern der Komponente einer Route erforderlich sind, langsam sind, haben Sie 2 Optionen
Standardmäßig zeigt TanStack Router eine ausstehende Komponente für Loader an, die länger als 1 Sekunde zum Auflösen benötigen. Dies ist ein optimistischer Schwellenwert, der konfiguriert werden kann über
Wenn der Schwellenwert für die Wartezeit überschritten wird, rendert der Router die Option pendingComponent der Route, falls konfiguriert.
Wenn Sie eine ausstehende Komponente verwenden, ist das Letzte, was Sie wollen, dass Ihr Wartezeit-Schwellenwert erreicht wird und Ihre Daten dann sofort danach aufgelöst werden, was zu einem störenden Aufleuchten Ihrer ausstehenden Komponente führt. Um dies zu vermeiden, **zeigt TanStack Router standardmäßig Ihre ausstehende Komponente für mindestens 500 ms an**. Dies ist ein optimistischer Schwellenwert, der konfiguriert werden kann über
TanStack Router bietet verschiedene Möglichkeiten, Fehler zu behandeln, die während des Routen-Lade-Lifecycles auftreten. Schauen wir sie uns an.
Die Option routeOptions.onError ist eine Funktion, die aufgerufen wird, wenn während des Routen-Ladens ein Fehler auftritt.
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
onError: ({ error }) => {
// Log the error
console.error(error)
},
})
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
onError: ({ error }) => {
// Log the error
console.error(error)
},
})
Die Option routeOptions.onCatch ist eine Funktion, die aufgerufen wird, wenn ein Fehler vom CatchBoundary des Routers abgefangen wurde.
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
onCatch: ({ error, errorInfo }) => {
// Log the error
console.error(error)
},
})
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
onCatch: ({ error, errorInfo }) => {
// Log the error
console.error(error)
},
})
Die Option routeOptions.errorComponent ist eine Komponente, die gerendert wird, wenn während des Routen-Lade- oder Rendering-Lifecycles ein Fehler auftritt. Sie wird mit den folgenden Props gerendert
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
errorComponent: ({ error }) => {
// Render an error message
return <div>{error.message}</div>
},
})
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
errorComponent: ({ error }) => {
// Render an error message
return <div>{error.message}</div>
},
})
Die Funktion reset kann verwendet werden, um dem Benutzer zu ermöglichen, das erneute Rendern der normalen Kinder der Fehlergrenze zu versuchen.
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
errorComponent: ({ error, reset }) => {
return (
<div>
{error.message}
<button
onClick={() => {
// Reset the router error boundary
reset()
}}
>
retry
</button>
</div>
)
},
})
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
errorComponent: ({ error, reset }) => {
return (
<div>
{error.message}
<button
onClick={() => {
// Reset the router error boundary
reset()
}}
>
retry
</button>
</div>
)
},
})
Wenn der Fehler das Ergebnis eines Routen-Ladevorgangs war, sollten Sie stattdessen router.invalidate() aufrufen, was sowohl einen Router-Neuladevorgang als auch ein Zurücksetzen der Fehlergrenze koordiniert.
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
errorComponent: ({ error, reset }) => {
const router = useRouter()
return (
<div>
{error.message}
<button
onClick={() => {
// Invalidate the route to reload the loader, which will also reset the error boundary
router.invalidate()
}}
>
retry
</button>
</div>
)
},
})
// routes/posts.tsx
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
errorComponent: ({ error, reset }) => {
const router = useRouter()
return (
<div>
{error.message}
<button
onClick={() => {
// Invalidate the route to reload the loader, which will also reset the error boundary
router.invalidate()
}}
>
retry
</button>
</div>
)
},
})
TanStack Router stellt eine Standard- ErrorComponent bereit, die gerendert wird, wenn während des Routen-Lade- oder Rendering-Lifecycles ein Fehler auftritt. Wenn Sie die Fehlerkomponenten Ihrer Routen überschreiben, ist es immer noch ratsam, alle nicht abgefangenen Fehler mit der Standard- ErrorComponent aufzufangen.
// routes/posts.tsx
import { createFileRoute, ErrorComponent } from '@tanstack/react-router'
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
errorComponent: ({ error }) => {
if (error instanceof MyCustomError) {
// Render a custom error message
return <div>{error.message}</div>
}
// Fallback to the default ErrorComponent
return <ErrorComponent error={error} />
},
})
// routes/posts.tsx
import { createFileRoute, ErrorComponent } from '@tanstack/react-router'
export const Route = createFileRoute('/posts')({
loader: () => fetchPosts(),
errorComponent: ({ error }) => {
if (error instanceof MyCustomError) {
// Render a custom error message
return <div>{error.message}</div>
}
// Fallback to the default ErrorComponent
return <ErrorComponent error={error} />
},
})
Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.