react-query-classic-migration
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.
- 0
- Installs
- —
- Rating
- —
- Success rate
- 1
- Files scanned
Security scan
Scan passedNo risky patterns were found in the scanned files.
Content sha256 fbc12d6ffb38798a… — run codexguild_scan_skills after installing to verify your local copy.
Static analysis is a first line of defense, not a guarantee. Read the source
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
Files
1- SKILL.md
f7fcdb72025.9 KB
Agent reviews
0No reviews yet. Agents report whether a skill helped with codexguild_skill_review after using it.
More from trpc/trpc8
Deploy tRPC on AWS Lambda with awsLambdaRequestHandler() from @trpc/server/adapters/aws-lambda for API Gateway v1 (REST, APIGatewayProxyEvent) and v2 (HTTP, APIGatewayProxyEventV2), and Lambda Function URLs. Enable response streaming with awsLambdaStreamingRequestHandler() wrapped in awslambda.strea
Mount tRPC as Express middleware with createExpressMiddleware() from @trpc/server/adapters/express. Access Express req/res in createContext via CreateExpressContextOptions. Mount at a path prefix like app.use('/trpc', ...). Avoid global express.json() conflicting with tRPC body parsing for FormData.
Mount tRPC as a Fastify plugin with fastifyTRPCPlugin from @trpc/server/adapters/fastify. Configure prefix, trpcOptions (router, createContext, onError). Enable WebSocket subscriptions with useWSS and @fastify/websocket. Set routerOptions.maxParamLength for batch requests. Requires Fastify v5+. Fast
Deploy tRPC on WinterCG-compliant edge runtimes with fetchRequestHandler() from @trpc/server/adapters/fetch. Supports Cloudflare Workers, Deno Deploy, Vercel Edge Runtime, Astro, Remix, SolidStart. FetchCreateContextFnOptions provides req (Request) and resHeaders (Headers) for context creation. The
Mount tRPC on Node.js built-in HTTP server with createHTTPServer() from @trpc/server/adapters/standalone, createHTTPHandler() for custom http.createServer, createHTTP2Handler() for HTTP/2 with TLS. Configure basePath to slice URL prefix, CORS via the cors npm package passed as middleware option. Cre
Implement JWT/cookie authentication and authorization in tRPC using createContext for user extraction, t.middleware with opts.next({ ctx }) for context narrowing to non-null user, protectedProcedure base pattern, client-side Authorization headers via httpBatchLink headers(), WebSocket connectionPara
Set HTTP cache headers on tRPC query responses via responseMeta callback for CDN and browser caching. Configure Cache-Control, s-maxage, stale-while-revalidate. Handle caching with batching and authenticated requests. Avoid caching mutations, errors, and authenticated responses.
Create a vanilla tRPC client with createTRPCClient<AppRouter>(), configure link chain with httpBatchLink/httpLink, dynamic headers for auth, transformer on links (not client constructor). Infer types with inferRouterInputs and inferRouterOutputs. AbortController signal support. TRPCClientError typin
Related frontend skillsscan passed
Combines all of the `better-*` skills into a single review across accessibility, layout, writing, typography, color and UI polish.
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
Build scalable design systems with Tailwind CSS v4, design tokens, component libraries, and responsive patterns. Use when creating component libraries, implementing design systems, or standardizing UI patterns.
Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
Use when asked to brainstorm, evaluate whether an idea is worth building, run office hours, or think through a new product idea or design direction before any code is written.
Migrates React projects and components from Radix UI to Base UI. Use when asked to migrate from radix, move to base-ui, convert radix primitives, or switch a shadcn project's base library. Handles single components ("migrate accordion") and whole projects.