new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

tRPC · all subjects

client/react-query

177 notes in this subject, read out of this brain and free to use. This is page 3 of 3.

useUtils returns additional properties

Beyond query helpers, useUtils returns a ProxyTRPCContextProps object with properties: client (the TRPCClient), ssrContext (the SSR context when server-side rendering, default null), ssrState (false for no SSR, 'prepass' during prepass, 'mounting' before TRPCProvider render, 'mounted' after TRPCProvider render, default false), and abortOnUnmount (abort loading query calls when unmounting a component, default false).

useUtils example with single query invalidation

Example showing invalidation on mutation success: ```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 }, }); } ```

useUtils example with full cache invalidation on mutation

Example showing how to invalidate full cache on every mutation: ```ts import { createTRPCReact } from '@trpc/react-query'; import type { AppRouter } from '../server'; export const trpc = createTRPCReact<AppRouter>({ overrides: { useMutation: { async onSuccess(opts) { await opts.originalFn(); await opts.queryClient.invalidateQueries(); }, }, }, }); ```

useUtils example with proxy client

Example showing proxy client usage to call procedures with async/await: ```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> ); } ```

getQueryKey helper for unimplemented functions

If you need a @tanstack/react-query function that isn't exposed via useUtils helpers, you can import and use it directly from @tanstack/react-query. tRPC also provides a getQueryKey helper to get the correct queryKey for use in filters with these functions.

TanStack React Query integration is recommended for new projects

TanStack React Query integration is the recommended way to use tRPC with React and TanStack Query for new projects. It should be used over the classic React Query integration.

TanStack React Query integration provides factory functions

The TanStack React Query integration for tRPC provides factories for common TanStack React Query interfaces like QueryKeys, QueryOptions, and MutationOptions, giving a more TanStack Query-native experience.

createTRPCContext creates type-safe context providers

The createTRPCContext function from @trpc/tanstack-react-query creates a set of type-safe context providers and consumers from your AppRouter type signature. It returns TRPCProvider, useTRPC, and useTRPCClient exports.

Example: creating tRPC context with createTRPCContext

import { createTRPCContext } from '@trpc/tanstack-react-query'; import type { AppRouter } from '../server/router'; export const { TRPCProvider, useTRPC, useTRPCClient } = createTRPCContext<AppRouter>();

QueryClient setup for SSR with staleTime recommendation

When using server-side rendering with the TanStack React Query integration, configure the QueryClient with defaultOptions.queries.staleTime set above 0 (such as 60 * 1000 milliseconds) to avoid refetching immediately on the client. For server rendering, create a new QueryClient for each request so users don't share the same cache.

Browser QueryClient singleton pattern to prevent re-creation

When creating a QueryClient for client-side rendering, use a singleton pattern where a browserQueryClient variable persists across renders. Check if browserQueryClient already exists before creating a new one, to avoid re-creating the client if React suspends during the initial render.

TanStack React Query integration is recommended over classic React Query

The TanStack React Query integration is simpler and more TanStack Query-native than the classic React Query integration. It provides factories for common TanStack React Query interfaces like QueryKeys, QueryOptions, and MutationOptions. The tRPC team recommends using this integration over the classic client.

TanStack React Query integration is optional

The TanStack React Query integration is fully optional. You can use @tanstack/react-query with just a vanilla tRPC client, although you will have to manually manage query keys and do not get the same level of DX as when using the integration package.

Example: TRPCProvider setup with React SSR

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { createTRPCClient, httpBatchLink } from '@trpc/client'; import { useState } from 'react'; import type { AppRouter } from '../server/router'; import { TRPCProvider } from '../utils/trpc'; function makeQueryClient() { return new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000, }, }, }); } let browserQueryClient: QueryClient | undefined = undefined; function getQueryClient() { if (typeof window === 'undefined') { return makeQueryClient(); } else { if (!browserQueryClient) browserQueryClient = makeQueryClient(); return browserQueryClient; } } export function App() { const queryClient = getQueryClient(); const [trpcClient] = useState(() => createTRPCClient<AppRouter>({ links: [ httpBatchLink({ url: 'http://localhost:2022', }), ], }), ); return ( <QueryClientProvider client={queryClient}> <TRPCProvider trpcClient={trpcClient} queryClient={queryClient}> {null} </TRPCProvider> </QueryClientProvider> ); }

SPA setup with createTRPCOptionsProxy for client-side only rendering

For SPAs using only client-side rendering (such as with Vite), create the QueryClient and tRPC client outside of React context as singletons. Use createTRPCOptionsProxy from @trpc/tanstack-react-query to create a tRPC proxy that combines the tRPC client and QueryClient.

Example: createTRPCOptionsProxy for client-side SPA

import { QueryClient } from '@tanstack/react-query'; import { createTRPCClient, httpBatchLink } from '@trpc/client'; import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query'; import type { AppRouter } from '../server/router'; export const queryClient = new QueryClient(); const trpcClient = createTRPCClient<AppRouter>({ links: [httpBatchLink({ url: 'http://localhost:2022' })], }); export const trpc = createTRPCOptionsProxy<AppRouter>({ client: trpcClient, queryClient, });

useTRPC hook provides typed access to tRPC procedures

The useTRPC hook from the TRPCProvider context gives you access to typed tRPC procedures. When using the singleton pattern with createTRPCOptionsProxy, you can import the trpc object directly instead of using the useTRPC hook.

queryOptions method generates TanStack React Query options

tRPC procedures have a queryOptions method that generates TanStack React Query QueryOptions. Call this method with procedure inputs to get options compatible with useQuery.

mutationOptions method generates TanStack React Query mutation options

tRPC procedures have a mutationOptions method that generates TanStack React Query MutationOptions. Use this with useMutation to get fully typed mutation options.

Example: using useQuery and useMutation with tRPC

import { useMutation, useQuery } from '@tanstack/react-query'; import { useTRPC } from '../utils/trpc'; export default function UserList() { const trpc = useTRPC(); const userQuery = useQuery(trpc.getUser.queryOptions({ id: 'id_bilbo' })); const userCreator = useMutation(trpc.createUser.mutationOptions()); return ( <div> <p>{userQuery.data?.name}</p> <button onClick={() => userCreator.mutate({ name: 'Frodo' })}> Create Frodo </button> </div> ); }

Query Key Prefixing available for queries and mutations

The TanStack React Query integration supports Query Key Prefixing to prefix all queries and mutations with a specific key. This is configured separately in setup and usage.

Reuse existing QueryClient if already using React Query

If you already use React Query in your application, you should re-use the QueryClient and QueryClientProvider you already have rather than creating a new one for tRPC.

Dependencies for TanStack React Query integration

Install the following packages: @trpc/server, @trpc/client, @trpc/tanstack-react-query, and @tanstack/react-query.

Direct client import for setup without React Context

When setting up without React Context, you can import the global client instance directly from your trpc file instead of using the useTRPCClient hook. This client can be used to call procedures directly.

useTRPC hook provides type-safe tRPC proxy object

The useTRPC hook provides a fully type-safe proxy object that mirrors your AppRouter structure. It offers autocomplete for all procedures in your router and provides methods like queryOptions, mutationOptions, queryKey, and mutationKey at the end of the proxy.

queryOptions method for type-safe query configuration

The queryOptions method is available on all query procedures. It accepts two arguments: the procedure input as the first argument, and any native TanStack React Query options as the second argument. It can also accept a trpc object with tRPC request options like context. The result can be passed to useQuery, useSuspenseQuery, or query client methods like fetchQuery and prefetchQuery.

skipToken for disabling queries in type-safe manner

You can disable a query using skipToken from @tanstack/react-query by passing it as the input to queryOptions instead of the actual input object. This provides a type-safe way to conditionally disable queries.

infiniteQueryOptions for cursor-based pagination

The infiniteQueryOptions method is available for query procedures that accept a cursor input. It provides a type-safe wrapper around TanStack's infiniteQueryOptions function. The first argument is the procedure input, and the second accepts any native TanStack React Query options like getNextPageParam.

queryKey method returns type-safe query keys

The queryKey method is available on all query procedures and allows you to access the query key in a type-safe manner. For nested routers, you can call pathKey() on intermediate routers to create partial query keys that match all queries in that sub-path using TanStack's fuzzy matching. You can also call pathKey() on the root trpc object to match all tRPC queries.

infiniteQueryKey for type-safe infinite query keys

The infiniteQueryKey method is available on query procedures that take a cursor input. It allows you to access the query key for an infinite query in a type-safe manner. The result can be used with query client methods like getQueryData, setQueryData, and invalidateQueries.

queryFilter method creates type-safe query filters

The queryFilter method is available on all query procedures and allows creating query filters in a type-safe manner. It accepts the procedure input as the first argument and any TanStack React Query filter options as the second argument, including a predicate function. You can also use pathFilter() on routers to target any sub-path and match all queries in that router.

infiniteQueryFilter for type-safe infinite query filters

The infiniteQueryFilter method is available on query procedures that take a cursor input. It allows creating query filters for infinite queries in a type-safe manner. It accepts the procedure input and any TanStack React Query filter options. The result can be passed to client methods like invalidateQueries.

mutationOptions for type-safe mutation configuration

The mutationOptions method is available on all mutation procedures. It provides a type-safe identity function for constructing options that can be passed to useMutation. It accepts any native TanStack React Query options like onSuccess callbacks.

mutationKey returns type-safe mutation keys

The mutationKey method is available on all mutation procedures and allows you to get the mutation key in a type-safe manner.

Query key prefixing for multiple tRPC providers

When using multiple tRPC providers in a single application connecting to different backend services, queries with the same path will collide in the cache. Enable query key prefixing by passing { keyPrefix: true } as the second generic argument to createTRPCContext. When providing contexts with prefixing, pass a keyPrefix prop to the TRPCProvider component to specify the prefix string.

Query key structure with prefixes

When query key prefixing is enabled, the query keys are structured as [['prefix'], ['path'], { type: 'query' }]. For example, with prefix 'billing', a list query key would be [['billing'], ['list'], { type: 'query' }].

useTRPCClient hook accesses tRPC client with React Context

When using the React Context setup with createTRPCContext, you can access the tRPC client using the useTRPCClient hook returned from createTRPCContext. This allows you to call procedures directly with the client instance.

TanStack React Query integration philosophy

The TanStack React Query integration is designed to provide thin and type-safe factories that work natively with TanStack React Query. By following the autocompletes provided by the client, developers can build applications using only the knowledge from the TanStack React Query documentation.

Quick example of queryOptions usage with useQuery

Example showing basic usage: const greetingQuery = useQuery(trpc.greeting.queryOptions({ name: 'Jerry' })); This creates a query with the greeting procedure, passing the input and returning data that can be accessed via greetingQuery.data.

tRPC client integration with SWR

tRPC-SWR is a tRPC adapter for Vercel's SWR client library.

useSubscription improvements

The useSubscription hook now returns information about the status of the subscription and connection. It also supports a ponyfill when using httpSubscriptionLink.

createTRPCReact basic setup

Create a tRPC React client by importing createTRPCReact from '@trpc/react-query', passing the AppRouter type as a generic parameter, and exporting it as a client instance. Example: export const trpc = createTRPCReact<AppRouter>();

useSuspenseQuery for suspense-based data fetching

Use useSuspenseQuery with tRPC queryOptions: useSuspenseQuery(trpc.user.byId.queryOptions({ id: '1' })). This throws a promise if data is not yet available, enabling React Suspense boundaries.

mutationOptions factory for type-safe mutations

Use trpc.procedure.mutationOptions(options?) to create mutation options. Example: useMutation(trpc.user.create.mutationOptions({ onSuccess: () => { ... } })). This provides type-safe input types and callback handlers.

Query invalidation with queryFilter

Use queryClient.invalidateQueries(trpc.procedure.queryFilter(input?)) to invalidate specific or grouped queries. Examples: invalidate a specific query with trpc.user.byId.queryFilter({ id: '1' }), all queries under a router with trpc.user.queryFilter(), or all tRPC queries with { queryKey: trpc.pathKey() }.

Direct cache read/write with queryKey

Use queryClient.getQueryData(trpc.procedure.queryKey(input)) to read cached data and queryClient.setQueryData(trpc.procedure.queryKey(input), data) to write to the cache. Example: const cached = queryClient.getQueryData(trpc.user.byId.queryKey({ id: '1' })).

infiniteQueryOptions for paginated data

Use trpc.procedure.infiniteQueryOptions(input, options?) with useInfiniteQuery. The options parameter accepts TanStack Query infinite query options like getNextPageParam. Example: useInfiniteQuery(trpc.post.list.infiniteQueryOptions({ limit: 10 }, { getNextPageParam: (lastPage) => lastPage.nextCursor })).

useTRPCClient hook for direct client calls

Use useTRPCClient() hook to access the tRPC client directly for imperative queries. Example: const client = useTRPCClient(); const result = await client.user.byId.query({ id: '1' });

Pitfall: useQuery without queryOptions factory loses type safety

Calling useQuery({ queryKey: [...], queryFn: ... }) manually bypasses tRPC's type-safe query key generation and loses autocomplete. Always use trpc.procedure.queryOptions() instead.

Query client default options staleTime configuration

Set default query options when creating a QueryClient. Example: new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000 } } }) sets all queries to be fresh for 60 seconds.

Pitfall: Classic utils.invalidate() pattern does not work with new package

The @trpc/tanstack-react-query package does not use utils.invalidate(). Use queryClient.invalidateQueries() with queryFilter() instead. Example: queryClient.invalidateQueries(trpc.post.queryFilter()).

queryOptions factory for type-safe queries

Use trpc.procedure.queryOptions(input, options?) to create query options. Example: useQuery(trpc.user.byId.queryOptions({ id: '1' })). This generates type-safe query keys automatically and supports TanStack Query options like staleTime.

Using skipToken for conditional queries

Use skipToken from '@tanstack/react-query' to conditionally skip a query. Example: useQuery(trpc.user.byId.queryOptions(userId ? { id: userId } : skipToken)). When skipToken is passed, the query does not execute.

Installation of @trpc/react-query

To install @trpc/react-query, run one of: npm install @trpc/react-query @tanstack/react-query, yarn add @trpc/react-query @tanstack/react-query, pnpm add @trpc/react-query @tanstack/react-query, or bun add @trpc/react-query @tanstack/react-query.

Create tRPC React hooks with createTRPCReact

Use createTRPCReact imported from @trpc/react-query to create tRPC hooks. Pass your AppRouter type as a generic argument: export const trpc = createTRPCReact<AppRouter>();

Query API using tRPC hooks

In any component, use the trpc proxy to call procedures. For example, trpc.greeting.useQuery({ name: 'tRPC' }) executes a useQuery hook that returns an object with data, error, and status properties.

@trpc/react-query package overview

@trpc/react-query is a tRPC wrapper around react-query that provides React Query integration for tRPC.

Give your agent this brain