Skip to main content
Version: 11.x

createTRPCQueryUtils

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.

note

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. 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.

caution

You should avoid using createTRPCQueryUtils in React Components. Instead, use useUtils which is a React hook that implements useCallback and useQueryClient under the hood.

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 component, when we navigate the object createTRPCQueryUtils gives us and reach the post.all query, we'll get access to our query helpers!

MyPage.tsx
tsx
import { QueryClient } from '@tanstack/react-query';
import { createTRPCQueryUtils, createTRPCReact } from '@trpc/react-query';
import { useLoaderData } from 'react-router-dom';
import type { AppRouter } from './server';
const trpc = createTRPCReact<AppRouter>();
const trpcClient = trpc.createClient({ links: [] });
const queryClient = new QueryClient();
const clientUtils = createTRPCQueryUtils({ queryClient, client: trpcClient });
// This is a react-router loader
export async function loader() {
const allPostsData = await clientUtils.post.all.ensureData(); // Fetches data if it doesn't exist in the cache
return {
allPostsData,
};
}
// This is a react component
export function Component() {
const loaderData = useLoaderData() as Awaited<ReturnType<typeof loader>>;
const allPostQuery = trpc.post.all.useQuery({
initialData: loaderData.allPostsData, // Uses the data from the loader
});
return (
<div>
{allPostQuery.data.posts.map((post) => (
<div key={post.id}>{post.title}</div>
))}
</div>
);
}
MyPage.tsx
tsx
import { QueryClient } from '@tanstack/react-query';
import { createTRPCQueryUtils, createTRPCReact } from '@trpc/react-query';
import { useLoaderData } from 'react-router-dom';
import type { AppRouter } from './server';
const trpc = createTRPCReact<AppRouter>();
const trpcClient = trpc.createClient({ links: [] });
const queryClient = new QueryClient();
const clientUtils = createTRPCQueryUtils({ queryClient, client: trpcClient });
// This is a react-router loader
export async function loader() {
const allPostsData = await clientUtils.post.all.ensureData(); // Fetches data if it doesn't exist in the cache
return {
allPostsData,
};
}
// This is a react component
export function Component() {
const loaderData = useLoaderData() as Awaited<ReturnType<typeof loader>>;
const allPostQuery = trpc.post.all.useQuery({
initialData: loaderData.allPostsData, // Uses the data from the loader
});
return (
<div>
{allPostQuery.data.posts.map((post) => (
<div key={post.id}>{post.title}</div>
))}
</div>
);
}
note

If you were using Remix Run or SSR you wouldn't re-use the same queryClient for every request. Instead, you would create a new queryClient for every request so that there's no cross-request data leakage.

Helpers

Much like useUtils, createTRPCQueryUtils gives you access to same set of helpers. The only difference is that you need to pass in the queryClient and client objects.

You can see them on the useUtils page.