rembrembdocs

useUtils is a hook 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

This hook was called useContext() until 10.41.0 (and is still aliased for the foreseeable future)

Usage

useUtils 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:

server.ts

ts

import { initTRPC } from '@trpc/server';

import { z } from 'zod';

const t = initTRPC.create();

const appRouter = t.router({

post: t.router({

`all: t.procedure.query(() => {`

  `return {`

    `posts: [`

      `{ id: 1, title: 'everlong' },`

      `{ id: 2, title: 'After Dark' },`

    `],`

  `};`

`}),`

}),

});

export type AppRouter = typeof appRouter;

Now in our component, when we navigate the object useUtils gives us and reach the post.all query, we'll get access to our query helpers!

MyComponent.tsx

tsx

import { createTRPCReact } from '@trpc/react-query';

import type { AppRouter } from './server';

const trpc = createTRPCReact<AppRouter>();

function MyComponent() {

const utils = trpc.useUtils();

utils.post.all.f;

}

Helpers

These are the helpers you'll get access to via useUtils. The table below will help you know which tRPC helper wraps which @tanstack/react-query helper method. Each react-query method will link to its respective docs/guide:

tRPC helper wrapper

@tanstack/react-query helper method

fetch

queryClient.fetchQuery

prefetch

queryClient.prefetchQuery

fetchInfinite

queryClient.fetchInfiniteQuery

prefetchInfinite

queryClient.prefetchInfiniteQuery

ensureData

queryClient.ensureData

invalidate

queryClient.invalidateQueries

refetch

queryClient.refetchQueries

cancel

queryClient.cancelQueries

setData

queryClient.setQueryData

setQueriesData

queryClient.setQueriesData

getData

queryClient.getQueryData

setInfiniteData

queryClient.setInfiniteQueryData

getInfiniteData

queryClient.getInfiniteData

setMutationDefaults

queryClient.setMutationDefaults

getMutationDefaults

queryClient.getMutationDefaults

isMutating

queryClient.isMutating

reset

queryClient.resetQueries

❓ The function I want isn't here​

@tanstack/react-query has a lot of functions that we haven't put in the tRPC context yet. If you need a function that isn't here, feel free to open a feature request requesting it.

In the meantime, you can import and use the function directly from @tanstack/react-query. We also provide a getQueryKey which you can use to get the correct queryKey on the filters when using these functions.

Proxy client

In addition to the above react-query helpers, the context also exposes your tRPC proxy client. This lets you call your procedures with async/await without needing to create an additional vanilla client.

tsx

import { useState } from 'react';

import { trpc } from './utils/trpc';

function MyComponent() {

const [apiKey, setApiKey] = useState('');

const utils = trpc.useUtils();

return (

`<form`

  `onSubmit={async (event) => {`

    `const apiKey = await utils.client.apiKey.create.mutate();`

    `setApiKey(apiKey);`

  `}}`

`>`

  `{/* form content */}`

`</form>`

);

}

Query Invalidation

You invalidate queries via the invalidate helper. invalidate is actually a special helper given that, unlike the other helpers, it's available at every level of the router map. This means you can either run invalidate on a single query, a whole router, or every router if you want. We get more in detail in the sections below.

Invalidating a single query

You can invalidate a query relating to a single procedure and even filter based on the input passed to it to prevent unnecessary calls to the back end.

Example code

tsx

import { trpc } from './utils/trpc';

function MyComponent() {

const utils = trpc.useUtils();

const mutation = trpc.post.edit.useMutation({

`onSuccess(input) {`

  `utils.post.all.invalidate();`

  `utils.post.byId.invalidate({ id: input.id }); // Will not invalidate queries for other id's`

`},`

});

// [...]

}

Invalidating across whole routers

It is also possible to invalidate queries across an entire router rather than just one query.

Example code

Backend code

tsx

import { trpc } from './utils/trpc';

function MyComponent() {

const utils = trpc.useUtils();

const invalidateAllQueriesAcrossAllRouters = () => {

`// 1️⃣`

`// All queries on all routers will be invalidated`

`utils.invalidate();`

};

const invalidateAllPostQueries = () => {

`// 2️⃣`

`// All post queries will be invalidated`

`utils.post.invalidate();`

};

const invalidatePostById = () => {

`// 3️⃣`

`// All queries in the post router with input {id:1} invalidated`

`utils.post.byId.invalidate({ id: 1 });`

};

// Example queries

trpc.user.all.useQuery(); // Would only be validated by 1️⃣ only.

trpc.post.all.useQuery(); // Would be invalidated by 1️⃣ & 2️⃣

trpc.post.byId.useQuery({ id: 1 }); // Would be invalidated by 1️⃣, 2️⃣ and 3️⃣

trpc.post.byId.useQuery({ id: 2 }); // would be invalidated by 1️⃣ and 2️⃣ but NOT 3️⃣!

// [...]

}

Invalidate full cache on every mutation

Keeping track of exactly what queries a mutation should invalidate is hard, therefore, it can be a pragmatic solution to invalidate the full cache as a side-effect on any mutation. Since we have request batching, this invalidation will simply refetch all queries on the page you're looking at in one single request.

We have added a feature to help with this:

ts

import { createTRPCReact } from '@trpc/react-query';

import type { AppRouter } from '../server';

export const trpc = createTRPCReact<AppRouter>({

overrides: {

`useMutation: {`

  `/**`

   ``* This function is called whenever a `.useMutation` succeeds``

   `**/`

  `async onSuccess(opts) {`

    `/**`

     `* @note that order here matters:`

     ``* The order here allows route changes in `onSuccess` without``

     `* having a flash of content change whilst redirecting.`

     `**/`

    ``// Calls the `onSuccess` defined in the `useQuery()`-options:``

    `await opts.originalFn();`

    `// Invalidate all queries in the react-query cache:`

    `await opts.queryClient.invalidateQueries();`

  `},`

`},`

},

});

Additional Options

Aside from the query helpers, the object useUtils returns also contains the following properties:

ts

interface ProxyTRPCContextProps<TRouter extends AnyRouter, TSSRContext> {

/**

* The `TRPCClient`

*/

client: TRPCClient<TRouter>;

/**

* The SSR context when server-side rendering

* @default null

*/

ssrContext?: TSSRContext | null;

/**

* State of SSR hydration.

* - `false` if not using SSR.

* - `prepass` when doing a prepass to fetch queries' data

* - `mounting` before TRPCProvider has been rendered on the client

* - `mounted` when the TRPCProvider has been rendered on the client

* @default false

*/

ssrState?: SSRState;

/**

* Abort loading query calls when unmounting a component - usually when navigating to a new page

* @default false

*/

abortOnUnmount?: boolean;

}