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.

Datos de origen

Repositorio
TanStack/router
Última actividad en el origen
5 de septiembre de 2026 a las 12:48
Idioma detectado de SKILL.md
inglés
Estrellas
15.202
Forks
1900

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
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
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub