- Spec files
npm-tanstack--react-router
Describes: pkg:npm/@tanstack/react-router@1.132.x
- Description
- Modern and scalable routing for React applications with built-in data fetching, caching, and state management capabilities
- Author
- tessl
- Last updated
How to use
npx @tessl/cli registry install tessl/npm-tanstack--react-router@1.132.0
react-hooks.md docs/
1# React Hooks23React hooks for accessing router state, navigation functions, route data, parameters, and managing router interactions. These hooks provide type-safe access to all router functionality.45## Capabilities67### Router Access Hooks89Hooks for accessing the router instance and router state.1011```typescript { .api }12/**13* Access the router instance14* @param opts - Options for router access15* @returns Router instance16*/17function useRouter<TRouter extends AnyRouter = RegisteredRouter>(18opts?: { warn?: boolean }19): TRouter;2021/**22* Subscribe to router state changes23* @param opts - Router state subscription options24* @returns Selected router state25*/26function useRouterState<27TRouter extends AnyRouter = RegisteredRouter,28TSelected = RouterState<TRouter>,29TStructuralSharing extends boolean = true30>(31opts?: {32router?: TRouter;33select?: (state: RouterState<TRouter>) => TSelected;34structuralSharing?: TStructuralSharing;35}36): UseRouterStateResult<TRouter, TSelected>;37```3839**Usage Examples:**4041```typescript42import { useRouter, useRouterState } from "@tanstack/react-router";4344function MyComponent() {45// Access router instance46const router = useRouter();4748// Subscribe to loading state49const isLoading = useRouterState({50select: (state) => state.isLoading,51});5253// Subscribe to current location54const location = useRouterState({55select: (state) => state.location,56});5758return (59<div>60Current path: {location.pathname}61{isLoading && <div>Loading...</div>}62</div>63);64}65```6667### Navigation Hooks6869Hooks for programmatic navigation and location access.7071```typescript { .api }72/**73* Get navigation function for programmatic navigation74* @param defaultOpts - Default navigation options75* @returns Type-safe navigation function76*/77function useNavigate<78TRouter extends AnyRouter = RegisteredRouter,79TDefaultFrom extends RoutePaths<TRouter> = "/"80>(81defaultOpts?: { from?: TDefaultFrom }82): UseNavigateResult<TRouter, TDefaultFrom>;8384/**85* Access current location with optional selection86* @param opts - Location access options87* @returns Current location or selected subset88*/89function useLocation<90TRouter extends AnyRouter = RegisteredRouter,91TSelected = ParsedLocation,92TStructuralSharing extends boolean = true93>(94opts?: {95select?: (location: ParsedLocation) => TSelected;96structuralSharing?: TStructuralSharing;97}98): UseLocationResult<TSelected>;99100/**101* Check if browser can navigate back102* @returns Whether back navigation is possible103*/104function useCanGoBack(): boolean;105```106107**Usage Examples:**108109```typescript110import { useNavigate, useLocation, useCanGoBack } from "@tanstack/react-router";111112function NavigationComponent() {113const navigate = useNavigate();114const location = useLocation();115const canGoBack = useCanGoBack();116117// Navigate programmatically118const handleNavigate = () => {119navigate({120to: "/posts/$postId",121params: { postId: "123" },122search: { tab: "comments" },123});124};125126// Navigate with state127const handleNavigateWithState = () => {128navigate({129to: "/profile",130state: { fromDashboard: true },131replace: true,132});133};134135return (136<div>137<p>Current path: {location.pathname}</p>138<button onClick={handleNavigate}>Go to Post</button>139<button onClick={() => navigate({ to: -1 })} disabled={!canGoBack}>140Go Back141</button>142</div>143);144}145```146147### Route Data Hooks148149Hooks for accessing route-specific data, parameters, and search values.150151```typescript { .api }152/**153* Access route parameters with type safety154* @param opts - Params access options155* @returns Route parameters or selected subset156*/157function useParams<158TRouter extends AnyRouter = RegisteredRouter,159TFrom extends RoutePaths<TRouter> = "/",160TStrict extends boolean = true,161TThrow extends boolean = true,162TSelected = ResolveParams<TRouter, TFrom>,163TStructuralSharing extends boolean = true164>(165opts?: {166from?: TFrom;167strict?: TStrict;168shouldThrow?: TThrow;169select?: (params: ResolveParams<TRouter, TFrom>) => TSelected;170structuralSharing?: TStructuralSharing;171}172): UseParamsResult<TRouter, TFrom, TStrict, TThrow, TSelected>;173174/**175* Access search parameters with type safety176* @param opts - Search access options177* @returns Search parameters or selected subset178*/179function useSearch<180TRouter extends AnyRouter = RegisteredRouter,181TFrom extends RoutePaths<TRouter> = "/",182TStrict extends boolean = true,183TThrow extends boolean = true,184TSelected = InferFullSearchSchema<TRouter, TFrom>,185TStructuralSharing extends boolean = true186>(187opts?: {188from?: TFrom;189strict?: TStrict;190shouldThrow?: TThrow;191select?: (search: InferFullSearchSchema<TRouter, TFrom>) => TSelected;192structuralSharing?: TStructuralSharing;193}194): UseSearchResult<TRouter, TFrom, TStrict, TThrow, TSelected>;195196/**197* Access loader data from route198* @param opts - Loader data access options199* @returns Loader data or selected subset200*/201function useLoaderData<202TRouter extends AnyRouter = RegisteredRouter,203TFrom extends RoutePaths<TRouter> = "/",204TStrict extends boolean = true,205TSelected = ResolveLoaderData<TRouter, TFrom>,206TStructuralSharing extends boolean = true207>(208opts?: {209from?: TFrom;210strict?: TStrict;211select?: (data: ResolveLoaderData<TRouter, TFrom>) => TSelected;212structuralSharing?: TStructuralSharing;213}214): UseLoaderDataResult<TRouter, TFrom, TStrict, TSelected>;215216/**217* Access loader dependencies218* @param opts - Loader deps access options219* @returns Loader dependencies220*/221function useLoaderDeps<222TRouter extends AnyRouter = RegisteredRouter,223TFrom extends RoutePaths<TRouter> = "/",224TStrict extends boolean = true,225TSelected = ResolveLoaderDeps<TRouter, TFrom>,226TStructuralSharing extends boolean = true227>(228opts?: {229from?: TFrom;230strict?: TStrict;231select?: (deps: ResolveLoaderDeps<TRouter, TFrom>) => TSelected;232structuralSharing?: TStructuralSharing;233}234): UseLoaderDepsResult<TRouter, TFrom, TStrict, TSelected>;235236/**237* Access route context238* @param opts - Route context access options239* @returns Route context or selected subset240*/241function useRouteContext<242TRouter extends AnyRouter = RegisteredRouter,243TFrom extends RoutePaths<TRouter> = "/",244TStrict extends boolean = true,245TSelected = RouteContext<TRouter, TFrom>,246TStructuralSharing extends boolean = true247>(248opts?: {249from?: TFrom;250strict?: TStrict;251select?: (context: RouteContext<TRouter, TFrom>) => TSelected;252structuralSharing?: TStructuralSharing;253}254): UseRouteContextResult<TRouter, TFrom, TStrict, TSelected>;255```256257**Usage Examples:**258259```typescript260import { useParams, useSearch, useLoaderData, useRouteContext } from "@tanstack/react-router";261262function PostDetail() {263// Access route parameters264const { postId } = useParams({ from: "/posts/$postId" });265266// Access search parameters with selection267const page = useSearch({268from: "/posts/$postId",269select: (search) => search.page || 1,270});271272// Access loader data273const { post, comments } = useLoaderData({ from: "/posts/$postId" });274275// Access route context276const user = useRouteContext({277select: (context) => context.user,278});279280return (281<div>282<h1>{post.title}</h1>283<p>Post ID: {postId}</p>284<p>Page: {page}</p>285<p>Viewing as: {user.name}</p>286</div>287);288}289```290291### Route Match Hooks292293Hooks for accessing route matches and match-related functionality.294295```typescript { .api }296/**297* Access route match data298* @param opts - Match access options299* @returns Route match or selected subset300*/301function useMatch<302TRouter extends AnyRouter = RegisteredRouter,303TFrom extends RoutePaths<TRouter> = "/",304TStrict extends boolean = true,305TThrow extends boolean = true,306TSelected = RouteMatch<TRouter, TFrom>,307TStructuralSharing extends boolean = true308>(309opts?: {310from?: TFrom;311strict?: TStrict;312shouldThrow?: TThrow;313select?: (match: RouteMatch<TRouter, TFrom>) => TSelected;314structuralSharing?: TStructuralSharing;315}316): UseMatchResult<TRouter, TFrom, TStrict, TThrow, TSelected>;317318/**319* Access all active route matches320* @param opts - Matches access options321* @returns Array of route matches or selected subset322*/323function useMatches<324TRouter extends AnyRouter = RegisteredRouter,325TSelected = RouteMatch[],326TStructuralSharing extends boolean = true327>(328opts?: {329select?: (matches: RouteMatch[]) => TSelected;330structuralSharing?: TStructuralSharing;331}332): UseMatchesResult<TSelected>;333334/**335* Access parent matches relative to current match336* @param opts - Parent matches access options337* @returns Array of parent matches or selected subset338*/339function useParentMatches<340TRouter extends AnyRouter = RegisteredRouter,341TSelected = RouteMatch[],342TStructuralSharing extends boolean = true343>(344opts?: {345select?: (matches: RouteMatch[]) => TSelected;346structuralSharing?: TStructuralSharing;347}348): UseMatchesResult<TSelected>;349350/**351* Access child matches relative to current match352* @param opts - Child matches access options353* @returns Array of child matches or selected subset354*/355function useChildMatches<356TRouter extends AnyRouter = RegisteredRouter,357TSelected = RouteMatch[],358TStructuralSharing extends boolean = true359>(360opts?: {361select?: (matches: RouteMatch[]) => TSelected;362structuralSharing?: TStructuralSharing;363}364): UseMatchesResult<TSelected>;365366/**367* Get function to check if routes match current location368* @returns Function that returns match params or false369*/370function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>(): (371opts: UseMatchRouteOptions<TRouter>372) => false | AllParams<TRouter>;373```374375**Usage Examples:**376377```typescript378import { useMatch, useMatches, useParentMatches, useMatchRoute } from "@tanstack/react-router";379380function RouteInfo() {381// Access current match382const match = useMatch();383384// Access all matches with breadcrumb info385const breadcrumbs = useMatches({386select: (matches) => matches.map(match => ({387id: match.id,388pathname: match.pathname,389title: match.context?.title || match.routeId,390})),391});392393// Access parent matches394const parentMatches = useParentMatches();395396// Check route matching397const matchRoute = useMatchRoute();398const isOnProfile = matchRoute({ to: "/profile" });399400return (401<div>402<nav>403{breadcrumbs.map((crumb) => (404<span key={crumb.id}>{crumb.title} / </span>405))}406</nav>407<p>Current match: {match.routeId}</p>408<p>Parent matches: {parentMatches.length}</p>409{isOnProfile && <p>Currently on profile page</p>}410</div>411);412}413```414415### Navigation Blocking Hooks416417Hooks for blocking navigation based on conditions.418419```typescript { .api }420/**421* Block navigation conditionally422* @param opts - Navigation blocking options423* @returns Blocker resolver if using resolver pattern424*/425function useBlocker<426TRouter extends AnyRouter = RegisteredRouter,427TWithResolver extends boolean = false428>(429opts: {430shouldBlockFn: ShouldBlockFn;431enableBeforeUnload?: boolean | (() => boolean);432disabled?: boolean;433withResolver?: TWithResolver;434}435): TWithResolver extends true ? BlockerResolver : void;436437type ShouldBlockFn = (438fromLocation: ParsedLocation,439toLocation: ParsedLocation440) => boolean;441442interface BlockerResolver {443status: "idle" | "blocked";444confirm: () => void;445cancel: () => void;446}447```448449**Usage Examples:**450451```typescript452import { useBlocker } from "@tanstack/react-router";453454function FormWithUnsavedChanges() {455const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);456457// Block navigation if there are unsaved changes458useBlocker({459shouldBlockFn: () => hasUnsavedChanges,460enableBeforeUnload: true,461});462463// With resolver pattern464const blocker = useBlocker({465shouldBlockFn: () => hasUnsavedChanges,466withResolver: true,467});468469return (470<form>471<input onChange={() => setHasUnsavedChanges(true)} />472473{blocker.status === "blocked" && (474<div>475<p>You have unsaved changes. Are you sure you want to leave?</p>476<button onClick={blocker.confirm}>Yes, leave</button>477<button onClick={blocker.cancel}>Stay</button>478</div>479)}480</form>481);482}483```484485### Async Data Hooks486487Hooks for handling deferred promises and async data.488489```typescript { .api }490/**491* Handle deferred promises with suspense492* @param options - Await options493* @returns Tuple of resolved data and promise state494*/495function useAwaited<T>(496options: AwaitOptions<T>497): [T, DeferredPromise<T>];498499interface AwaitOptions<T> {500/** Promise to await */501promise: Promise<T>;502}503504interface DeferredPromise<T> extends Promise<T> {505__deferredState: DeferredPromiseState<T>;506}507508interface DeferredPromiseState<T> {509status: "pending" | "success" | "error";510data?: T;511error?: any;512}513```514515**Usage Examples:**516517```typescript518import { useAwaited, defer } from "@tanstack/react-router";519520function AsyncDataComponent() {521const { deferredPosts } = useLoaderData();522523try {524const [posts, promise] = useAwaited({ promise: deferredPosts });525526return (527<div>528<h2>Posts (Status: {promise.__deferredState.status})</h2>529{posts.map(post => (530<div key={post.id}>{post.title}</div>531))}532</div>533);534} catch (promise) {535// This will suspend until the promise resolves536throw promise;537}538}539```540541### Link Props Hook542543Hook for getting link element props with all link logic applied.544545```typescript { .api }546/**547* Get props for link elements with all link logic548* @param options - Link options549* @param forwardedRef - Optional forwarded ref550* @returns Props object for anchor element551*/552function useLinkProps<553TRouter extends AnyRouter = RegisteredRouter,554TFrom extends string = string,555TTo extends string | undefined = undefined,556TMaskFrom extends string = TFrom,557TMaskTo extends string = ""558>(559options: UseLinkPropsOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,560forwardedRef?: React.ForwardedRef<Element>561): React.ComponentPropsWithRef<"a">;562563interface UseLinkPropsOptions<TRouter extends AnyRouter, TFrom extends string, TTo extends string | undefined, TMaskFrom extends string, TMaskTo extends string>564extends LinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> {565/** Disabled state */566disabled?: boolean;567}568```569570**Usage Examples:**571572```typescript573import { useLinkProps } from "@tanstack/react-router";574575function CustomLink({ to, children, ...props }) {576const linkProps = useLinkProps({577to,578activeProps: { className: "active" },579preload: "intent",580...props,581});582583return (584<a {...linkProps} className={`custom-link ${linkProps.className || ""}`}>585{children}586</a>587);588}589```590591### Utility Hooks592593Utility hooks for common React patterns and DOM interactions.594595```typescript { .api }596/**597* Hook for accessing previous values across renders598* @param value - Current value599* @returns Previous value or null if no previous value600*/601function usePrevious<T>(value: T): T | null;602603/**604* Hook for stable callback references that don't cause re-renders605* @param fn - Function to stabilize606* @returns Stable function reference607*/608function useStableCallback<T extends (...args: Array<any>) => any>(fn: T): T;609610/**611* Hook for working with forwarded refs612* @param ref - Forwarded ref from React.forwardRef613* @returns Inner ref that can be used on DOM elements614*/615function useForwardedRef<T>(ref?: React.ForwardedRef<T>): React.RefObject<T>;616617/**618* Hook for IntersectionObserver functionality619* @param ref - Ref to element to observe620* @param callback - Callback when intersection changes621* @param intersectionObserverOptions - IntersectionObserver options622* @param options - Hook-specific options623*/624function useIntersectionObserver<T extends Element>(625ref: React.RefObject<T | null>,626callback: (entry: IntersectionObserverEntry | undefined) => void,627intersectionObserverOptions?: IntersectionObserverInit,628options?: { disabled?: boolean }629): void;630631/**632* Hook for custom element scroll restoration633* @param options - Scroll restoration configuration634* @returns Scroll restoration entry if available635*/636function useElementScrollRestoration(637options: (638| {639id: string;640getElement?: () => Window | Element | undefined | null;641}642| {643id?: string;644getElement: () => Window | Element | undefined | null;645}646) & {647getKey?: (location: ParsedLocation) => string;648}649): ScrollRestorationEntry | undefined;650```651652**Usage Examples:**653654```typescript655import {656usePrevious,657useStableCallback,658useForwardedRef,659useIntersectionObserver,660useElementScrollRestoration,661} from "@tanstack/react-router";662663// Previous value tracking664function CounterComponent({ count }: { count: number }) {665const prevCount = usePrevious(count);666667return (668<div>669Current: {count}, Previous: {prevCount}670</div>671);672}673674// Stable callbacks to prevent re-renders675function ExpensiveComponent({ onUpdate }: { onUpdate: (data: any) => void }) {676const stableOnUpdate = useStableCallback(onUpdate);677678// This won't cause child re-renders when onUpdate reference changes679return <ChildComponent onUpdate={stableOnUpdate} />;680}681682// Forwarded refs683const CustomInput = React.forwardRef<HTMLInputElement>((props, ref) => {684const innerRef = useForwardedRef(ref);685686return <input ref={innerRef} {...props} />;687});688689// Intersection observer690function LazyImage({ src, alt }: { src: string; alt: string }) {691const [isVisible, setIsVisible] = useState(false);692const imgRef = useRef<HTMLImageElement>(null);693694useIntersectionObserver(695imgRef,696(entry) => {697if (entry?.isIntersecting) {698setIsVisible(true);699}700},701{ rootMargin: "100px" }702);703704return (705<img706ref={imgRef}707src={isVisible ? src : undefined}708alt={alt}709/>710);711}712713// Element scroll restoration714function CustomScrollableComponent() {715const containerRef = useRef<HTMLDivElement>(null);716717const scrollEntry = useElementScrollRestoration({718id: "custom-scrollable",719getElement: () => containerRef.current,720});721722useEffect(() => {723if (scrollEntry && containerRef.current) {724containerRef.current.scrollTop = scrollEntry.scrollY;725}726}, [scrollEntry]);727728return <div ref={containerRef}>...</div>;729}730```731732## Types733734### Hook Result Types735736```typescript { .api }737type UseNavigateResult<TRouter extends AnyRouter, TDefaultFrom extends RoutePaths<TRouter>> =738<TTo extends RoutePaths<TRouter> = "/", TFrom extends RoutePaths<TRouter> = TDefaultFrom>(739options: NavigateOptions<TRouter, TFrom, TTo>740) => Promise<void>;741742type UseLocationResult<TSelected> = TSelected extends ParsedLocation743? ParsedLocation744: TSelected;745746type UseParamsResult<TRouter extends AnyRouter, TFrom extends RoutePaths<TRouter>, TStrict extends boolean, TThrow extends boolean, TSelected> =747TStrict extends false748? TThrow extends false749? TSelected | undefined750: TSelected751: TSelected;752753type UseSearchResult<TRouter extends AnyRouter, TFrom extends RoutePaths<TRouter>, TStrict extends boolean, TThrow extends boolean, TSelected> =754TStrict extends false755? TThrow extends false756? TSelected | undefined757: TSelected758: TSelected;759760type UseMatchesResult<TSelected> = TSelected;761```762763### Hook Options Types764765```typescript { .api }766interface UseMatchRouteOptions<TRouter extends AnyRouter = AnyRouter> {767to: RoutePaths<TRouter>;768params?: Record<string, any>;769search?: Record<string, any>;770hash?: string;771fuzzy?: boolean;772includeSearch?: boolean;773includeHash?: boolean;774}775```