
Skill
react-query-classic-migration
migrate tRPC to TanStack React Query
Description
Migrate from @trpc/react-query (classic) to @trpc/tanstack-react-query. Run npx @trpc/upgrade CLI for automated codemod. Manually migrate remaining patterns: hook-based to options-factory, utils.invalidate to queryClient.invalidateQueries with queryFilter, provider changes.
SKILL.md
This skill builds on react-query-setup. Read it first for foundational concepts.
tRPC -- Classic React Query Migration
Overview
This skill covers migrating from @trpc/react-query (the classic tRPC React hooks) to @trpc/tanstack-react-query (the new options-factory client). The two packages can coexist in the same application, so you can migrate incrementally.
Step 1: Run the upgrade CLI
npx @trpc/upgrade
When prompted, select:
Migrate Hooks to queryOptions/mutationOptions APIMigrate context provider setup
The codemod handles common patterns but is a work in progress. Always typecheck after running it.
Step 2: Install the new package
npm install @trpc/tanstack-react-query
You can keep @trpc/react-query installed during the migration period.
Step 3: Set up the new provider
Replace the classic createTRPCReact setup with createTRPCContext:
// BEFORE (classic)
import { createTRPCReact } from '@trpc/react-query';
import type { AppRouter } from '../server/router';
export const trpc = createTRPCReact<AppRouter>();
// AFTER (new)
import { createTRPCContext } from '@trpc/tanstack-react-query';
import type { AppRouter } from '../server/router';
export const { TRPCProvider, useTRPC } = createTRPCContext<AppRouter>();
Update the provider in your app root:
// BEFORE (classic)
// trpc.Provider wrapping with queryClient and client props
// AFTER (new)
import { QueryClientProvider } from '@tanstack/react-query';
import { TRPCProvider } from '../utils/trpc';
<QueryClientProvider client={queryClient}>
<TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
{children}
</TRPCProvider>
</QueryClientProvider>;
Migration Patterns
Queries
// BEFORE (classic)
import { trpc } from './trpc';
function Users() {
const greeting = trpc.greeting.useQuery({ name: 'Jerry' });
}
// AFTER (new)
import { useQuery } from '@tanstack/react-query';
import { useTRPC } from './trpc';
function Users() {
const trpc = useTRPC();
const greeting = useQuery(trpc.greeting.queryOptions({ name: 'Jerry' }));
}
Mutations
// BEFORE (classic)
import { trpc } from './trpc';
function Users() {
const createUser = trpc.createUser.useMutation();
createUser.mutate({ name: 'Jerry' });
}
// AFTER (new)
import { useMutation } from '@tanstack/react-query';
import { useTRPC } from './trpc';
function Users() {
const trpc = useTRPC();
const createUser = useMutation(trpc.createUser.mutationOptions());
createUser.mutate({ name: 'Jerry' });
}
Query invalidation
// BEFORE (classic)
import { trpc } from './trpc';
function Users() {
const utils = trpc.useUtils();
async function invalidateGreeting() {
await utils.greeting.invalidate({ name: 'Jerry' });
}
}
// AFTER (new)
import { useQueryClient } from '@tanstack/react-query';
import { useTRPC } from './trpc';
function Users() {
const trpc = useTRPC();
const queryClient = useQueryClient();
async function invalidateGreeting() {
await queryClient.invalidateQueries(
trpc.greeting.queryFilter({ name: 'Jerry' }),
);
}
}
Other QueryClient operations
Any classic trpc.useUtils() usage maps to standard TanStack Query useQueryClient() calls:
Classic (utils.xxx) | New (queryClient + trpc) |
|---|---|
utils.post.invalidate() | queryClient.invalidateQueries(trpc.post.queryFilter()) |
utils.post.refetch() | queryClient.refetchQueries(trpc.post.queryFilter()) |
utils.post.getData(input) | queryClient.getQueryData(trpc.post.byId.queryKey(input)) |
utils.post.setData(input,d) | queryClient.setQueryData(trpc.post.byId.queryKey(input),d) |
Step 4: Typecheck and fix
After migrating all files (or a batch of files), run TypeScript to catch remaining issues:
npx tsc --noEmit
Common type errors after migration:
- Missing
useTRPC()call (the new pattern requires calling the hook inside the component) - Incorrect options shape (
queryOptionstakes the procedure input as the first arg;mutationOptionstakes TanStack Query options likeonSuccess/onError, with mutation variables passed later tomutate(...)) useUtils()references that need to becomeuseQueryClient()+useTRPC()pairs
Step 5: Remove classic package
Once all files are migrated and TypeScript passes:
npm uninstall @trpc/react-query
Common Mistakes
Assuming the codemod handles everything
npx @trpc/upgrade is a work-in-progress codemod. It handles common patterns but may miss complex cases like dynamic query keys, conditional hooks, or custom wrappers around tRPC hooks. Always run tsc --noEmit after the codemod completes and fix remaining errors manually.
Mixing classic and new hooks in the same component
While the classic and new packages can coexist in the same app, mixing their hooks in the same component creates confusing dual-provider requirements and makes the code harder to reason about. Migrate one component at a time, converting all hooks in that component from classic to new in a single pass.
See Also
- react-query-setup -- full setup guide for the new @trpc/tanstack-react-query package
- nextjs-app-router -- if migrating a Next.js app to App Router at the same time
More skills from the trpc repository
View all 24 skillsadapter-aws-lambda
deploy tRPC APIs on AWS Lambda
Jul 18API DevelopmentAWSBackendtRPCadapter-express
mount tRPC as Express middleware
Jul 18API DevelopmentBackendExpresstRPCadapter-fastify
mount tRPC as a Fastify plugin
Jul 18API DevelopmentBackendFastifytRPCadapter-fetch
deploy tRPC on edge runtimes
Jul 18CloudflareDeploymentEdgetRPC +1adapter-standalone
mount tRPC on Node.js servers
Jul 18API DevelopmentBackendNode.jstRPCauth
implement authentication in tRPC applications
Jul 18AuthAuthenticationBackendtRPC
More from tRPC
View publishercaching
configure HTTP caching for tRPC queries
trpc
Jul 18BackendCachingPerformancetRPCclient-setup
set up vanilla tRPC clients
trpc
Jul 18API DevelopmentFrontendtRPCerror-handling
implement typed error handling in tRPC
trpc
Jul 18BackendDebuggingtRPCTypeScriptlinks
configure tRPC client link chains
trpc
Jul 18API DevelopmentFrontendtRPCmiddlewares
compose middleware for tRPC procedures
trpc
Jul 18BackendMiddlewaretRPCnextjs-app-router
implement tRPC in Next.js App Router
trpc
Jul 18BackendFrontendNext.jstRPC +1