Skip to content

Commit e63a25c

Browse files
committed
useRoute: type-safe data access for other routes on the page
1 parent e8319a8 commit e63a25c

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

packages/react-router/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export {
144144
useRouteError,
145145
useRouteLoaderData,
146146
useRoutes,
147+
useRoute,
147148
} from "./lib/hooks";
148149

149150
// Expose old RR DOM API

packages/react-router/lib/hooks.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,13 @@ import {
5050
resolveTo,
5151
stripBasename,
5252
} from "./router/utils";
53-
import type { SerializeFrom } from "./types/route-data";
53+
import type {
54+
GetActionData,
55+
GetLoaderData,
56+
SerializeFrom,
57+
} from "./types/route-data";
5458
import type { unstable_ClientOnErrorFunction } from "./components";
59+
import type { RouteModules } from "./types/register";
5560

5661
/**
5762
* Resolves a URL against the current {@link Location}.
@@ -1838,3 +1843,19 @@ function warningOnce(key: string, cond: boolean, message: string) {
18381843
warning(false, message);
18391844
}
18401845
}
1846+
1847+
type UseRoute<T extends keyof RouteModules> = {
1848+
loaderData: GetLoaderData<RouteModules[T]>;
1849+
actionData: GetActionData<RouteModules[T]>;
1850+
};
1851+
export function useRoute<T extends keyof RouteModules>(
1852+
routeId: T,
1853+
): UseRoute<T> | undefined {
1854+
const state = useDataRouterState(DataRouterStateHook.UseRouteLoaderData);
1855+
const route = state.matches.find(({ route }) => route.id === routeId);
1856+
if (route === undefined) return undefined;
1857+
return {
1858+
loaderData: state.loaderData[routeId],
1859+
actionData: state.actionData?.[routeId],
1860+
};
1861+
}

packages/react-router/lib/types/register.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { RouteModule } from "./route-module";
2+
13
/**
24
* Apps can use this interface to "register" app-wide types for React Router via interface declaration merging and module augmentation.
35
* React Router should handle this for you via type generation.
@@ -7,6 +9,7 @@
79
export interface Register {
810
// pages
911
// routeFiles
12+
// routeModules
1013
}
1114

1215
// pages
@@ -25,3 +28,10 @@ export type RouteFiles = Register extends {
2528
}
2629
? Registered
2730
: AnyRouteFiles;
31+
32+
type AnyRouteModules = Record<string, RouteModule>;
33+
export type RouteModules = Register extends {
34+
routeModules: infer Registered extends AnyRouteModules;
35+
}
36+
? Registered
37+
: AnyRouteModules;

0 commit comments

Comments
 (0)