T
TanStack4w ago
xenial-black

How to infer the type of Route component with the context of it?

Let's say I have this component:
import { createFileRoute } from "@tanstack/react-router";

import { Stack, Title } from "@mantine/core";

import { ReturnReasonTable } from "./-components/table";

export const Route = createFileRoute("/(dashboard)/utilities/return-reason/")({
loader: async ({ context: { queryClient, trpc } }) =>
await queryClient.ensureQueryData(trpc.returnReason.getReturnReasons.queryOptions()),
component: ReturnReasonPage,
head: () => ({
meta: [
{
title: "Return Reason",
},
],
}),
});

function ReturnReasonPage() {
const { session } = Route.useRouteContext();

return (
<Stack>
<Title order={4}>Return Reason</Title>

<ReturnReasonTable session={session} />
</Stack>
);
}
import { createFileRoute } from "@tanstack/react-router";

import { Stack, Title } from "@mantine/core";

import { ReturnReasonTable } from "./-components/table";

export const Route = createFileRoute("/(dashboard)/utilities/return-reason/")({
loader: async ({ context: { queryClient, trpc } }) =>
await queryClient.ensureQueryData(trpc.returnReason.getReturnReasons.queryOptions()),
component: ReturnReasonPage,
head: () => ({
meta: [
{
title: "Return Reason",
},
],
}),
});

function ReturnReasonPage() {
const { session } = Route.useRouteContext();

return (
<Stack>
<Title order={4}>Return Reason</Title>

<ReturnReasonTable session={session} />
</Stack>
);
}
I want to create a function that passes Route but I don't know how to infer the type of Route with the context in it (I have trpc, queryClient, session, and error). I'm trying to create this component as a kind of pre process for ReturnReasonPage to check if the user has a permission.
import { redirect } from "@tanstack/react-router";

import { paths } from "#lib/paths.ts";

import { type Action, type Resource, checkPermission } from "@repo/shared/lib";

import type { Session } from "#lib/auth-client.ts";

export type WithAuthProps = {
session: Session;
};

export function withAuth<T extends WithAuthProps>(
Route: unknown,
Component: React.ComponentType<T>,
resource?: Resource,
action?: Action
) {
return async function AuthenticatedComponent(props: Omit<T, keyof WithAuthProps>) {
const { session } = Route.useRouteContext();

if (!session) {
redirect({ to: paths.auth.signIn });
}

if (resource && action && !checkPermission({ resource, action, session })) {
redirect({ to: "/401" });
}

return (
<Component
{...(props as T)}
session={session}
/>
);
};
}
import { redirect } from "@tanstack/react-router";

import { paths } from "#lib/paths.ts";

import { type Action, type Resource, checkPermission } from "@repo/shared/lib";

import type { Session } from "#lib/auth-client.ts";

export type WithAuthProps = {
session: Session;
};

export function withAuth<T extends WithAuthProps>(
Route: unknown,
Component: React.ComponentType<T>,
resource?: Resource,
action?: Action
) {
return async function AuthenticatedComponent(props: Omit<T, keyof WithAuthProps>) {
const { session } = Route.useRouteContext();

if (!session) {
redirect({ to: paths.auth.signIn });
}

if (resource && action && !checkPermission({ resource, action, session })) {
redirect({ to: "/401" });
}

return (
<Component
{...(props as T)}
session={session}
/>
);
};
}
2 Replies
xenial-black
xenial-blackOP4w ago
I used export type Route = typeof Route but this feels like a dirty solution. Hoping there's a better one. This is a dumb approach. I didn't realize I could just get the RouteContext anywhere with useRouterContext no need to solve this.
extended-salmon
extended-salmon4w ago
you can also use getRouteApi

Did you find this page helpful?