Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/framework/react/api/router/AnyRouteMatchType.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ title: AnyRouteMatch type
The `AnyRouteMatch` type represents a route match in TanStack Router that is not specific to a particular route.

```tsx
type AnyRouteMatch = RouteMatch<any, any>
type AnyRouteMatch = RouteMatch<any, any, any, any, any, any, any>
```

- [`RouteMatch`](../RouteMatchType)
90 changes: 50 additions & 40 deletions packages/react-router/src/Matches.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
import * as React from 'react'
import invariant from 'tiny-invariant'
import warning from 'tiny-warning'
import { set } from 'zod'
import { CatchBoundary, ErrorComponent } from './CatchBoundary'
import { useRouterState } from './useRouterState'
import { useRouter } from './useRouter'
import { createControlledPromise, pick } from './utils'
import { CatchNotFound, DefaultGlobalNotFound, isNotFound } from './not-found'
import { isRedirect } from './redirects'
import {
type AnyRouter,
type RegisteredRouter,
type RouterState,
} from './router'
import { type AnyRouter, type RegisteredRouter } from './router'
import type { ResolveRelativePath, ToOptions } from './link'
import type {
AnyRoute,
ReactNode,
RootSearchSchema,
StaticDataRouteOption,
} from './route'
import type { AnyRoute, ReactNode, StaticDataRouteOption } from './route'
import type {
AllParams,
FullSearchSchema,
Expand All @@ -40,39 +30,34 @@ import type {
export const matchContext = React.createContext<string | undefined>(undefined)

export interface RouteMatch<
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
TReturnIntersection extends boolean = false,
TRouteId,
TAllParams,
TFullSearchSchema,
TLoaderData,
TAllContext,
TRouteContext,
TLoaderDeps,
> {
id: string
routeId: TRouteId
pathname: string
params: TReturnIntersection extends false
? RouteById<TRouteTree, TRouteId>['types']['allParams']
: Expand<Partial<AllParams<TRouteTree>>>
params: TAllParams
status: 'pending' | 'success' | 'error' | 'redirected' | 'notFound'
isFetching: boolean
error: unknown
paramsError: unknown
searchError: unknown
updatedAt: number
loadPromise: ControlledPromise<void>
loaderPromise: Promise<RouteById<TRouteTree, TRouteId>['types']['loaderData']>
loaderData?: RouteById<TRouteTree, TRouteId>['types']['loaderData']
routeContext: RouteById<TRouteTree, TRouteId>['types']['routeContext']
context: RouteById<TRouteTree, TRouteId>['types']['allContext']
search: TReturnIntersection extends false
? Exclude<
RouteById<TRouteTree, TRouteId>['types']['fullSearchSchema'],
RootSearchSchema
>
: Expand<
Partial<Omit<FullSearchSchema<TRouteTree>, keyof RootSearchSchema>>
>
loaderPromise: Promise<TLoaderData>
loaderData?: TLoaderData
routeContext: TRouteContext
context: TAllContext
search: TFullSearchSchema
fetchCount: number
abortController: AbortController
cause: 'preload' | 'enter' | 'stay'
loaderDeps: RouteById<TRouteTree, TRouteId>['types']['loaderDeps']
loaderDeps: TLoaderDeps
preload: boolean
invalid: boolean
meta?: Array<JSX.IntrinsicElements['meta']>
Expand All @@ -84,7 +69,32 @@ export interface RouteMatch<
minPendingPromise?: ControlledPromise<void>
}

export type AnyRouteMatch = RouteMatch<any, any>
export type MakeRouteMatch<
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
TRouteId = ParseRoute<TRouteTree>['id'],
TReturnIntersection extends boolean = false,
TTypes extends AnyRoute['types'] = RouteById<TRouteTree, TRouteId>['types'],
TAllParams = TReturnIntersection extends false
? TTypes['allParams']
: Partial<AllParams<TRouteTree>>,
TFullSearchSchema = TReturnIntersection extends false
? TTypes['fullSearchSchema']
: Partial<FullSearchSchema<TRouteTree>>,
TLoaderData = TTypes['loaderData'],
TAllContext = TTypes['allContext'],
TRouteContext = TTypes['routeContext'],
TLoaderDeps = TTypes['loaderDeps'],
> = RouteMatch<
TRouteId,
TAllParams,
TFullSearchSchema,
TLoaderData,
TAllContext,
TRouteContext,
TLoaderDeps
>

export type AnyRouteMatch = RouteMatch<any, any, any, any, any, any, any>

export function Matches() {
const matchId = useRouterState({
Expand Down Expand Up @@ -503,11 +513,11 @@ export function useMatch<
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
TReturnIntersection extends boolean = false,
TRouteMatchState = RouteMatch<TRouteTree, TFrom, TReturnIntersection>,
TSelected = TRouteMatchState,
TRouteMatch = MakeRouteMatch<TRouteTree, TFrom, TReturnIntersection>,
TSelected = TRouteMatch,
>(
opts: StrictOrFrom<TFrom, TReturnIntersection> & {
select?: (match: TRouteMatchState) => TSelected
select?: (match: TRouteMatch) => TSelected
},
): TSelected {
const nearestMatchId = React.useContext(matchContext)
Expand Down Expand Up @@ -536,7 +546,7 @@ export function useMatches<
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
TReturnIntersection extends boolean = false,
TRouteMatch = RouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
T = Array<TRouteMatch>,
>(opts?: {
select?: (matches: Array<TRouteMatch>) => T
Expand All @@ -556,7 +566,7 @@ export function useParentMatches<
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
TReturnIntersection extends boolean = false,
TRouteMatch = RouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
T = Array<TRouteMatch>,
>(opts?: {
select?: (matches: Array<TRouteMatch>) => T
Expand All @@ -581,7 +591,7 @@ export function useChildMatches<
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
TReturnIntersection extends boolean = false,
TRouteMatch = RouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId, TReturnIntersection>,
T = Array<TRouteMatch>,
>(opts?: {
select?: (matches: Array<TRouteMatch>) => T
Expand All @@ -604,7 +614,7 @@ export function useChildMatches<
export function useLoaderDeps<
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
TRouteMatch extends RouteMatch<TRouteTree, TFrom> = RouteMatch<
TRouteMatch extends MakeRouteMatch<TRouteTree, TFrom> = MakeRouteMatch<
TRouteTree,
TFrom
>,
Expand All @@ -627,7 +637,7 @@ export function useLoaderDeps<
export function useLoaderData<
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
TRouteMatch extends RouteMatch<TRouteTree, TFrom> = RouteMatch<
TRouteMatch extends MakeRouteMatch<TRouteTree, TFrom> = MakeRouteMatch<
TRouteTree,
TFrom
>,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-router/src/RouterProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type {
RouterState,
} from './router'

import type { RouteMatch } from './Matches'
import type { MakeRouteMatch } from './Matches'

export interface CommitLocationOptions {
replace?: boolean
Expand Down Expand Up @@ -229,7 +229,7 @@ function Transitioner() {
export function getRouteMatch<TRouteTree extends AnyRoute>(
state: RouterState<TRouteTree>,
id: string,
): undefined | RouteMatch<TRouteTree> {
): undefined | MakeRouteMatch<TRouteTree> {
return [
...state.cachedMatches,
...(state.pendingMatches ?? []),
Expand Down
28 changes: 22 additions & 6 deletions packages/react-router/src/fileRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import type {
UpdatableRouteOptions,
} from './route'
import type { Assign, IsAny } from './utils'
import type { RouteMatch } from './Matches'
import type { MakeRouteMatch } from './Matches'
import type { NoInfer } from '@tanstack/react-store'
import type { RegisteredRouter } from './router'
import type { RouteById, RouteIds } from './routeInfo'
Expand Down Expand Up @@ -189,7 +189,15 @@ export class FileRoute<
TLoaderDeps,
TLoaderDataReturn
> &
UpdatableRouteOptions<TAllParams, TFullSearchSchema, TLoaderData>,
UpdatableRouteOptions<
TId,
TAllParams,
TFullSearchSchema,
TLoaderData,
TAllContext,
TRouteContext,
TLoaderDeps
>,
): Route<
TParentRoute,
TPath,
Expand Down Expand Up @@ -255,7 +263,15 @@ export function FileRouteLoader<
}

export type LazyRouteOptions = Pick<
UpdatableRouteOptions<AnyPathParams, AnySearchSchema, any>,
UpdatableRouteOptions<
string,
AnyPathParams,
AnySearchSchema,
{},
AnyContext,
AnyContext,
{}
>,
'component' | 'errorComponent' | 'pendingComponent' | 'notFoundComponent'
>

Expand All @@ -274,13 +290,13 @@ export class LazyRoute<TRoute extends AnyRoute> {
}

useMatch = <
TRouteMatchState = RouteMatch<
TRouteMatch = MakeRouteMatch<
RegisteredRouter['routeTree'],
TRoute['types']['id']
>,
TSelected = TRouteMatchState,
TSelected = TRouteMatch,
>(opts?: {
select?: (match: TRouteMatchState) => TSelected
select?: (match: TRouteMatch) => TSelected
}): TSelected => {
return useMatch({ select: opts?.select, from: this.options.id })
}
Expand Down
Loading