Hoppa till huvudinnehållet
Version: 10.x

Härleda typer

Inofficiell Beta-översättning

Denna sida har översatts av PageTurner AI (beta). Inte officiellt godkänd av projektet. Hittade du ett fel? Rapportera problem →

Utöver den typinferens som tillhandahålls av @trpc/server (se här) erbjuder denna integration även några inferenshjälpmedel som är specifikt utformade för användning i React.

Härled React Query-alternativ baserat på din router

När du skapar anpassade hooks runt tRPC-procedurer kan det ibland vara nödvändigt att låta alternativens typer härledas från routern. Detta kan du göra via hjälpmedlet inferReactQueryProcedureOptions som exporteras från @trpc/react-query.

trpc.ts
ts
import {
createTRPCReact,
type inferReactQueryProcedureOptions,
} from '@trpc/react-query';
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
import type { AppRouter } from './server';
 
// infer the types for your router
export type ReactQueryOptions = inferReactQueryProcedureOptions<AppRouter>;
export type RouterInputs = inferRouterInputs<AppRouter>;
export type RouterOutputs = inferRouterOutputs<AppRouter>;
 
export const trpc = createTRPCReact<AppRouter>();
trpc.ts
ts
import {
createTRPCReact,
type inferReactQueryProcedureOptions,
} from '@trpc/react-query';
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
import type { AppRouter } from './server';
 
// infer the types for your router
export type ReactQueryOptions = inferReactQueryProcedureOptions<AppRouter>;
export type RouterInputs = inferRouterInputs<AppRouter>;
export type RouterOutputs = inferRouterOutputs<AppRouter>;
 
export const trpc = createTRPCReact<AppRouter>();
usePostCreate.ts
ts
import {
trpc,
type ReactQueryOptions,
type RouterInputs,
type RouterOutputs,
} from './trpc';
 
type PostCreateOptions = ReactQueryOptions['post']['create'];
 
function usePostCreate(options?: PostCreateOptions) {
const utils = trpc.useUtils();
 
return trpc.post.create.useMutation({
...options,
onSuccess(post) {
// invalidate all queries on the post router
// when a new post is created
utils.post.invalidate();
options?.onSuccess?.(post);
},
});
}
usePostCreate.ts
ts
import {
trpc,
type ReactQueryOptions,
type RouterInputs,
type RouterOutputs,
} from './trpc';
 
type PostCreateOptions = ReactQueryOptions['post']['create'];
 
function usePostCreate(options?: PostCreateOptions) {
const utils = trpc.useUtils();
 
return trpc.post.create.useMutation({
...options,
onSuccess(post) {
// invalidate all queries on the post router
// when a new post is created
utils.post.invalidate();
options?.onSuccess?.(post);
},
});
}
usePostById.ts
ts
import { ReactQueryOptions, RouterInputs, trpc } from './trpc';
 
type PostByIdOptions = ReactQueryOptions['post']['byId'];
type PostByIdInput = RouterInputs['post']['byId'];
 
function usePostById(input: PostByIdInput, options?: PostByIdOptions) {
return trpc.post.byId.useQuery(input, options);
}
usePostById.ts
ts
import { ReactQueryOptions, RouterInputs, trpc } from './trpc';
 
type PostByIdOptions = ReactQueryOptions['post']['byId'];
type PostByIdInput = RouterInputs['post']['byId'];
 
function usePostById(input: PostByIdInput, options?: PostByIdOptions) {
return trpc.post.byId.useQuery(input, options);
}

Härled abstrakta typer från en "Router Factory"

Om du skriver en factory som skapar ett liknande routergränssnitt flera gånger i din applikation, kan du vilja dela klientkod mellan olika användningar av factoryn. @trpc/react-query/shared exporterar flera typer som kan användas för att generera abstrakta typer för en router-factory, och bygga gemensamma React-komponenter som får routern skickad som en prop.

api/factory.ts
tsx
import { t, publicProcedure } from './trpc';
 
// @trpc/react-query/shared exports several **Like types which can be used to generate abstract types
import { RouterLike, UtilsLike } from '@trpc/react-query/shared';
 
// Factory function written by you, however you need,
// so long as you can infer the resulting type of t.router() later
export function createMyRouter() {
return t.router({
createThing: publicProcedure
.input(ThingRequest)
.output(Thing)
.mutation(/* do work */),
listThings: publicProcedure
.input(ThingQuery)
.output(ThingArray)
.query(/* do work */),
})
}
 
// Infer the type of your router, and then generate the abstract types for use in the client
type MyRouterType = ReturnType<typeof createMyRouter>
export MyRouterLike = RouterLike<MyRouterType>
export MyRouterUtilsLike = UtilsLike<MyRouterType>
api/factory.ts
tsx
import { t, publicProcedure } from './trpc';
 
// @trpc/react-query/shared exports several **Like types which can be used to generate abstract types
import { RouterLike, UtilsLike } from '@trpc/react-query/shared';
 
// Factory function written by you, however you need,
// so long as you can infer the resulting type of t.router() later
export function createMyRouter() {
return t.router({
createThing: publicProcedure
.input(ThingRequest)
.output(Thing)
.mutation(/* do work */),
listThings: publicProcedure
.input(ThingQuery)
.output(ThingArray)
.query(/* do work */),
})
}
 
// Infer the type of your router, and then generate the abstract types for use in the client
type MyRouterType = ReturnType<typeof createMyRouter>
export MyRouterLike = RouterLike<MyRouterType>
export MyRouterUtilsLike = UtilsLike<MyRouterType>
api/server.ts
tsx
export type AppRouter = typeof appRouter;
 
// Export your MyRouter types to the client
export type { MyRouterLike, MyRouterUtilsLike } from './factory';
api/server.ts
tsx
export type AppRouter = typeof appRouter;
 
// Export your MyRouter types to the client
export type { MyRouterLike, MyRouterUtilsLike } from './factory';
frontend/usePostCreate.ts
tsx
import type { MyRouterLike, MyRouterUtilsLike, trpc, useUtils } from './trpc';
 
type MyGenericComponentProps = {
route: MyRouterLike;
utils: MyRouterUtilsLike;
};
 
function MyGenericComponent(props: MyGenericComponentProps) {
const { route } = props;
const thing = route.listThings.useQuery({
filter: 'qwerty',
});
 
const mutation = route.doThing.useMutation({
onSuccess() {
props.utils.listThings.invalidate();
},
});
 
function handleClick() {
mutation.mutate({
name: 'Thing 1',
});
}
 
return; /* ui */
}
 
function MyPageComponent() {
const utils = useUtils();
 
return (
<MyGenericComponent
route={trpc.deep.route.things}
utils={utils.deep.route.things}
/>
);
}
 
function MyOtherPageComponent() {
const utils = useUtils();
 
return (
<MyGenericComponent
route={trpc.different.things}
utils={utils.different.things}
/>
);
}
frontend/usePostCreate.ts
tsx
import type { MyRouterLike, MyRouterUtilsLike, trpc, useUtils } from './trpc';
 
type MyGenericComponentProps = {
route: MyRouterLike;
utils: MyRouterUtilsLike;
};
 
function MyGenericComponent(props: MyGenericComponentProps) {
const { route } = props;
const thing = route.listThings.useQuery({
filter: 'qwerty',
});
 
const mutation = route.doThing.useMutation({
onSuccess() {
props.utils.listThings.invalidate();
},
});
 
function handleClick() {
mutation.mutate({
name: 'Thing 1',
});
}
 
return; /* ui */
}
 
function MyPageComponent() {
const utils = useUtils();
 
return (
<MyGenericComponent
route={trpc.deep.route.things}
utils={utils.deep.route.things}
/>
);
}
 
function MyOtherPageComponent() {
const utils = useUtils();
 
return (
<MyGenericComponent
route={trpc.different.things}
utils={utils.different.things}
/>
);
}

Ett mer komplett fungerande exempel finns här