Skip to main content

react-router

React bindings for TanStack Router: RouterProvider, useRouter, useRouterState, useMatch, useMatches, useLocation, useSearch, useParams, useNavigate, useLoaderData, useLoaderDeps, useRouteContext, useBlocker, useCanGoBack, Link, Navigate, Outlet, CatchBoundary, ErrorComponent. React-specific patterns for hooks, providers, SSR hydration, and createLink with forwardRef.

Quellinformationen

Repository
TanStack/router
Letzte Quellaktivität
5. September 2026 um 12:48
Erkannte Sprache von SKILL.md
Englisch
Sterne
15.202
Forks
1.900

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
react-router
description
React bindings for TanStack Router: RouterProvider, useRouter, useRouterState, useMatch, useMatches, useLocation, useSearch, useParams, useNavigate, useLoaderData, useLoaderDeps, useRouteContext, useBlocker, useCanGoBack, Link, Navigate, Outlet, CatchBoundary, ErrorComponent. React-specific patterns for hooks, providers, SSR hydration, and createLink with forwardRef.
metadata
{"type":"framework","library":"tanstack-router","library_version":"1.166.2","framework":"react"}
requires
["router-core"]
sources
["TanStack/router:packages/react-router/src","TanStack/router:docs/router/guide/creating-a-router.md","TanStack/router:docs/router/installation/manual.md"]
# React Router (`@tanstack/react-router`) This skill builds on router-core. Read [router-core](../../../router-core/skills/router-core/SKILL.md) first for foundational concepts. > **CRITICAL**: TanStack Router types are FULLY INFERRED. Never cast, never annotate inferred values. > **CRITICAL**: TanStack Router is CLIENT-FIRST. Loaders run on the client by default, not on the server. > **CRITICAL**: Do not confuse `@tanstack/react-router` with `react-router-dom`/`react-router`. They are completely different libraries with different APIs. ## Full Setup: File-Based Routing with Vite ### 1. Install Dependencies ```bash npm install @tanstack/react-router npm install -D @tanstack/router-plugin @tanstack/react-router-devtools ``` ### 2. Configure Vite Plugin ```ts // vite.config.ts import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { tanstackRouter } from '@tanstack/router-plugin/vite' export default defineConfig({ plugins: [ // MUST come before react() tanstackRouter({ target: 'react', autoCodeSplitting: true, }), react(), ], }) ``` ### 3. Create Root Route ```tsx // src/routes/__root.tsx import { createRootRoute, Link, Outlet } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' export const Route = createRootRoute({ component: RootLayout, }) function RootLayout() { return ( <> <nav> <Link to="/" className="[&.active]:font-bold"> Home </Link> <Link to="/about" className="[&.active]:font-bold"> About </Link> </nav> <hr /> <Outlet /> <TanStackRouterDevtools /> </> ) } ``` ### 4. Create Route Files ```tsx // src/routes/index.tsx import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/')({ component: HomePage, }) function HomePage() { return <h1>Welcome Home</h1> } ``` ```tsx // src/routes/about.tsx import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/about')({ component: AboutPage, }) function AboutPage() { return <h1>About</h1> } ``` ### 5. Create Router Instance and Register Types ```tsx // src/main.tsx import { StrictMode } from 'react' import ReactDOM from 'react-dom/client' import { RouterProvider, createRouter } from '@tanstack/react-router' import { routeTree } from './routeTree.gen' const router = createRouter({ routeTree }) // REQUIRED — without this, Link/useNavigate/useSearch have no type safety declare module '@tanstack/react-router' { interface Register { router: typeof router } } const rootElement = document.getElementById('root')! if (!rootElement.innerHTML) { const root = ReactDOM.createRoot(rootElement) root.render( <StrictMode> <RouterProvider router={router} /> </StrictMode>, ) } ``` ## Hooks Reference All hooks are imported from `@tanstack/react-router`. ### `useRouter()` Access the router instance directly: ```tsx import { useRouter } from '@tanstack/react-router' function InvalidateButton() { const router = useRouter() return <button onClick={() => router.invalidate()}>Refresh data</button> } ``` ### `useRouterState()` Subscribe to router state changes. Exposes the entire state and thus incurs a performance cost. For matches or location favor `useMatches` and `useLocation`. ```tsx import { useRouterState } from '@tanstack/react-router' function LoadingIndicator() { const isLoading = useRouterState({ select: (s) => s.isLoading }) return isLoading ? <div>Loading...</div> : null } ``` ### `useNavigate()` Programmatic navigation (prefer `<Link>` for user-clickable elements): ```tsx import { useNavigate } from '@tanstack/react-router' function AfterSubmit() { const navigate = useNavigate() const handleSubmit = async () => { await saveData() navigate({ to: '/posts/$postId', params: { postId: '123' } }) } return <button onClick={handleSubmit}>Save</button> } ``` ### `useSearch({ from })` Read validated search params: ```tsx import { useSearch } from '@tanstack/react-router' function Pagination() { const { page } = useSearch({ from: '/products' }) return <span>Page {page}</span> } ``` ### `useParams({ from })` Read path params: ```tsx import { useParams } from '@tanstack/react-router' function PostHeader() { const { postId } = useParams({ from: '/posts/$postId' }) return <h2>Post {postId}</h2> } ``` ### `useLoaderData({ from })` Read data returned from the route loader: ```tsx import { useLoaderData } from '@tanstack/react-router' function PostContent() { const { post } = useLoaderData({ from: '/posts/$postId' }) return <article>{post.content}</article> } ``` ### `useMatch({ from })` Access the full route match (params, search, loader data, context): ```tsx import { useMatch } from '@tanstack/react-router' function PostDetails() { const match = useMatch({ from: '/posts/$postId' }) return <div>{match.loaderData.post.title}</div> } ``` ### Other Hooks All imported from `@tanstack/react-router`: - **`useMatches()`** — array of all active route matches (useful for breadcrumbs) - **`useRouteContext({ from })`** — read context from `beforeLoad` or parent routes - **`useBlocker({ shouldBlockFn })`** — block navigation for unsaved changes - **`useCanGoBack()`** — returns `boolean`, check if history has entries to go back to - **`useLocation()`** — current parsed location (`pathname`, `search`, `hash`) - **`useLinkProps({ to, params?, search? })`** — get `<a>` props for custom link elements - **`useMatchRoute()`** — returns a function: `matchRoute({ to }) => match | false` ## Components Reference ### `RouterProvider` Mount the router at the top of your React tree: ```tsx <RouterProvider router={router} /> ``` ### `Link` Type-safe navigation link with `<a>` semantics: ```tsx <Link to="/posts/$postId" params={{ postId: '42' }}> View Post </Link> ``` ### `Outlet` Renders the matched child route component: ```tsx function Layout() { return ( <div> <Sidebar /> <main> <Outlet /> </main> </div> ) } ``` ### `Navigate` Declarative redirect component: ```tsx import { Navigate } from '@tanstack/react-router' function OldPage() { return <Navigate to="/new-page" /> } ``` ### `Await` Renders deferred data from unawaited loader promises with Suspense: ```tsx import { Await } from '@tanstack/react-router' import { Suspense } from 'react' function PostWithComments() { const { deferredComments } = Route.useLoaderData() return ( <div> <h1>Post</h1> <Suspense fallback={<div>Loading comments...</div>}> <Await promise={deferredComments}> {(comments) => ( <ul> {comments.map((c) => ( <li key={c.id}>{c.text}</li> ))} </ul> )} </Await> </Suspense> </div> ) } ``` ### `CatchBoundary` Error boundary for component-level error handling (route-level errors use `errorComponent` route option): ```tsx import { CatchBoundary } from '@tanstack/react-router' ;<CatchBoundary getResetKey={() => 'widget'} onCatch={(error) => console.error(error)} errorComponent={({ error }) => <div>{String(error)}</div>} > <RiskyWidget /> </CatchBoundary> ``` ## React-Specific Patterns ### Custom Link Component with `createLink` Wrap `Link` in a custom component while preserving type safety: ```tsx import { createLink } from '@tanstack/react-router' import { forwardRef, type ComponentPropsWithoutRef } from 'react' const StyledLinkComponent = forwardRef< HTMLAnchorElement, ComponentPropsWithoutRef<'a'> >((props, ref) => ( <a ref={ref} {...props} className={`styled-link ${props.className ?? ''}`} /> )) const StyledLink = createLink(StyledLinkComponent) // Usage — same type-safe props as Link function Nav() { return ( <StyledLink to="/posts/$postId" params={{ postId: '42' }}> Post </StyledLink> ) } ``` ### Reusable Components with Router Hooks To create a component that uses router hooks across multiple routes, pass a union of route paths as the `from` prop: ```tsx function PostIdDisplay({ from }: { from: '/posts/$id' | '/drafts/$id' }) { const { id } = useParams({ from }) return <span>ID: {id}</span> } // Usage in different route components <PostIdDisplay from="/posts/$id" /> <PostIdDisplay from="/drafts/$id" /> ``` This pattern avoids `strict: false` (which returns an imprecise union) while keeping the component reusable across specific known routes. ### Auth Provider Must Wrap RouterProvider If routes use auth context (via `createRootRouteWithContext`), the auth provider must be an ancestor of `RouterProvider`: ```tsx // CORRECT — AuthProvider wraps RouterProvider function App() { return ( <AuthProvider> <RouterProvider router={router} /> </AuthProvider> ) } // WRONG — RouterProvider outside auth provider function App() { return ( <RouterProvider router={router}> <AuthProvider>{/* ... */}</AuthProvider> </RouterProvider> ) } ``` Or use the `Wrap` router option to provide context without wrapping externally: ```tsx const router = createRouter({ routeTree, Wrap: ({ children }) => ( <QueryClientProvider client={queryClient}>{children}</QueryClientProvider> ), }) ``` ## Common Mistakes ### 1. HIGH: Using React hooks in `beforeLoad` or `loader` `beforeLoad` and `loader` are NOT React components — they are plain async functions. React hooks cannot be called in them. Pass auth state via router context instead. ```tsx // WRONG — useAuth is a React hook, cannot be called here beforeLoad: () => { const auth = useAuth() if (!auth.user) throw redirect({ to: '/login' }) } // CORRECT — read auth from router context beforeLoad: ({ context }) => { if (!context.auth.isAuthenticated) { throw redirect({ to: '/login' }) } } ``` ### 2. HIGH: Wrapping RouterProvider inside an auth provider incorrectly
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen