createTRPCQueryUtils
On this page
The use case for createTRPCQueryUtils is when you need to use the helpers outside of a React Component, for example in react-router's loaders.
Similar to useUtils, createTRPCQueryUtils is a function that gives you access to helpers that let you manage the cached data of the queries you execute via @trpc/react-query. These helpers are actually thin wrappers around @tanstack/react-query's queryClient methods. If you want more in-depth information about options and usage patterns for useUtils helpers than what we provide here, we will link to their respective @tanstack/react-query docs so you can refer to them accordingly.
The difference between useUtils and createTRPCQueryUtils is that useUtils is a react hook that uses useQueryClient under the hood. This means that it is able to work better within React Components.
If you need access to the client directly, you can use the client object that you passed to createTRPCQueryUtils during creation.
Usage
createTRPCQueryUtils returns an object with all the available queries you have in your routers. You use it the same way as your trpc client object. Once you reach a query, you'll have access to the query helpers. For example, let's say you have a post router with an all query:
Now in our route loader, when we navigate the object createTRPCQueryUtils gives us and reach the post.all query, we'll get access to our query helpers!
import { class QueryClientQueryClient } from '@tanstack/react-query';
import { function createTRPCQueryUtils<TRouter extends AnyRouter>(opts: CreateQueryUtilsOptions<TRouter>): CreateQueryUtils<TRouter>createTRPCQueryUtils, function createTRPCReact<TRouter extends AnyRouter, TSSRContext = unknown>(opts?: CreateTRPCReactOptions<TRouter>): CreateTRPCReact<TRouter, TSSRContext>createTRPCReact } from '@trpc/react-query';
import type { type AppRouter = Router<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>> & DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>
AppRouter } from './server';
const const trpc: CreateTRPCReactBase<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>, unknown> & DecorateRouterRecord<...>
trpc = createTRPCReact<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>, unknown>(opts?: CreateTRPCReactOptions<...> | undefined): CreateTRPCReactBase<...> & DecorateRouterRecord<...>
createTRPCReact<type AppRouter = Router<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>> & DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>
AppRouter>();
const const trpcClient: TRPCClient<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>>
trpcClient = const trpc: CreateTRPCReactBase<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>, unknown> & DecorateRouterRecord<...>
trpc.createClient: (opts: CreateTRPCClientOptions<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>>) => TRPCClient<...>
createClient({ links: TRPCLink<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>>[]
links: [] });
const const queryClient: QueryClientqueryClient = new new QueryClient(config?: QueryClientConfig): QueryClientQueryClient();
const const clientUtils: CreateQueryUtils<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>>
clientUtils = createTRPCQueryUtils<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>>(opts: CreateQueryUtilsOptions<...>): CreateQueryUtils<...>
createTRPCQueryUtils({ CreateQueryUtilsOptions<TRouter extends AnyRouter>.queryClient: QueryClientqueryClient, CreateQueryUtilsOptions<BuiltRouter<{ ctx: object; meta: object; errorShape: DefaultErrorShape; transformer: false; }, DecorateCreateRouterOptions<{ post: BuiltRouter<{ ctx: object; meta: object; errorShape: DefaultErrorShape; transformer: false; }, DecorateCreateRouterOptions<...>>; }>>>.client: TRPCClient<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>> | TRPCUntypedClient<...>
client: const trpcClient: TRPCClient<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>>
trpcClient });
// This is a react-router loader
export async function function loader(): Promise<{
allPostsData: {
posts: {
id: number;
title: string;
}[];
};
}>
loader() {
const const allPostsData: {
posts: {
id: number;
title: string;
}[];
}
allPostsData = await const clientUtils: CreateQueryUtils<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>>
clientUtils.post: DecorateRouter & {
all: DecorateQueryProcedure<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>>;
}
post.all: DecorateQueryProcedure<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>>
all.function ensureData(input: void, opts?: TRPCFetchQueryOptions<{
posts: {
id: number;
title: string;
}[];
}, TRPCClientError<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}>> | undefined): Promise<{
posts: {
id: number;
title: string;
}[];
}>
ensureData(); // Fetches data if it doesn't exist in the cache
return {
allPostsData: {
posts: {
id: number;
title: string;
}[];
}
allPostsData,
};
}
// This is a react component
export function function Component(): React.JSX.ElementComponent() {
const const loaderData: {
allPostsData: {
posts: {
id: number;
title: string;
}[];
};
}
loaderData = function useLoaderData(): unknownuseLoaderData() as type Awaited<T> = T extends null | undefined ? T : T extends object & {
then(onfulfilled: infer F, ...args: infer _): any;
} ? F extends (value: infer V, ...args: infer _) => any ? Awaited<V> : never : T
Awaited<type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : anyReturnType<typeof function loader(): Promise<{
allPostsData: {
posts: {
id: number;
title: string;
}[];
};
}>
loader>>;
const const allPostQuery: DefinedUseTRPCQueryResult<{
posts: {
id: number;
title: string;
}[];
}, TRPCClientErrorLike<{
errorShape: DefaultErrorShape;
transformer: false;
}>>
allPostQuery = const trpc: CreateTRPCReactBase<BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
post: BuiltRouter<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>;
}>>, unknown> & DecorateRouterRecord<...>
trpc.post: DecorateRouterRecord<{
ctx: object;
meta: object;
errorShape: DefaultErrorShape;
transformer: false;
}, DecorateCreateRouterOptions<{
all: QueryProcedure<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
meta: object;
errorShape: DefaultErrorShape;
}>;
}>>
post.all: DecoratedQuery<{
input: void;
output: {
posts: {
id: number;
title: string;
}[];
};
transformer: false;
errorShape: DefaultErrorShape;
}>
all.useQuery: ProcedureUseQuery
<{
posts: {
id: number;
title: string;
}[];
}, {
posts: {
id: number;
title: string;
}[];
}>(input: void | unique symbol, opts: DefinedUseTRPCQueryOptions<{
posts: {
id: number;
title: string;
}[];
}, {
posts: {
id: number;
title: string;
}[];
}, TRPCClientErrorLike<{
errorShape: DefaultErrorShape;
transformer: false;
}>, {
posts: {
id: number;
title: string;
}[];
}>) => DefinedUseTRPCQueryResult<{
posts: {
id: number;
title: string;
}[];
}, TRPCClientErrorLike<{
errorShape: DefaultErrorShape;
transformer: false;
}>> (+1 overload)
useQuery(var undefinedundefined, {
DefinedUseTRPCQueryOptions<{ posts: { id: number; title: string; }[]; }, { posts: { id: number; title: string; }[]; }, TRPCClientErrorLike<{ errorShape: DefaultErrorShape; transformer: false; }>, { posts: { id: number; title: string; }[]; }>.initialData: {
posts: {
id: number;
title: string;
}[];
} | InitialDataFunction<{
posts: {
id: number;
title: string;
}[];
}>
initialData: const loaderData: {
allPostsData: {
posts: {
id: number;
title: string;
}[];
};
}
loaderData.allPostsData: {
posts: {
id: number;
title: string;
}[];
}
allPostsData, // Uses the data from the loader
});
return (
<React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>
{const allPostQuery: DefinedUseTRPCQueryResult<{
posts: {
id: number;
title: string;
}[];
}, TRPCClientErrorLike<{
errorShape: DefaultErrorShape;
transformer: false;
}>>
allPostQuery.data: {
posts: {
id: number;
title: string;
}[];
}
data.posts: {
id: number;
title: string;
}[]
posts.Array<{ id: number; title: string; }>.map<React.JSX.Element>(callbackfn: (value: {
id: number;
title: string;
}, index: number, array: {
id: number;
title: string;
}[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
map((post: {
id: number;
title: string;
}
post) => (
<React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.Attributes.key?: React.Key | null | undefinedkey={post: {
id: number;
title: string;
}
post.id: numberid}>{post: {
id: number;
title: string;
}
post.title: stringtitle}</React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>
))}
</React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>
);
}Helpers
Much like useUtils, createTRPCQueryUtils gives you access to same set of helpers, including queryOptions and infiniteQueryOptions. The only difference is that you need to pass in the queryClient and client objects.
You can see them on the useUtils-page.