Set up the React Query Integration
1. Install dependencies
The following dependencies should be installed
- npm
- yarn
- pnpm
- bun
npm install @trpc/server@next @trpc/client@next @trpc/react-query@next @trpc/next@next @tanstack/react-query@latest
yarn add @trpc/server@next @trpc/client@next @trpc/react-query@next @trpc/next@next @tanstack/react-query@latest
pnpm add @trpc/server@next @trpc/client@next @trpc/react-query@next @trpc/next@next @tanstack/react-query@latest
bun add @trpc/server@next @trpc/client@next @trpc/react-query@next @trpc/next@next @tanstack/react-query@latest
2. Import your AppRouter
Import your AppRouter
type into the client application. This type holds the shape of your entire API.
ts
import type {AppRouter } from '../server/router';
ts
import type {AppRouter } from '../server/router';
By using import type
you ensure that the reference will be stripped at compile-time, meaning you don't inadvertently import server-side code into your client. For more information, see the Typescript docs.
3. Create tRPC hooks
Create a set of strongly-typed React hooks from your AppRouter
type signature with createTRPCReact
.
utils/trpc.tsts
import {createTRPCReact } from '@trpc/react-query';import type {AppRouter } from '../server/router';export consttrpc =createTRPCReact <AppRouter >();
utils/trpc.tsts
import {createTRPCReact } from '@trpc/react-query';import type {AppRouter } from '../server/router';export consttrpc =createTRPCReact <AppRouter >();
4. Add tRPC providers
Create a tRPC client, and wrap your application in the tRPC Provider, as below. You will also need to set up and connect React Query, which they document in more depth.
If you already use React Query in your application, you should re-use the QueryClient
and QueryClientProvider
you already have.
App.tsxtsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';import { httpBatchLink } from '@trpc/client';import React, { useState } from 'react';import { trpc } from './utils/trpc';export function App() {const [queryClient] = useState(() => new QueryClient());const [trpcClient] = useState(() =>trpc.createClient({links: [httpBatchLink({url: 'http://localhost:3000/trpc',// You can pass any HTTP headers you wish hereasync headers() {return {authorization: getAuthCookie(),};},}),],}),);return (<trpc.Provider client={trpcClient} queryClient={queryClient}><QueryClientProvider client={queryClient}>{/* Your app here */}</QueryClientProvider></trpc.Provider>);}
App.tsxtsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';import { httpBatchLink } from '@trpc/client';import React, { useState } from 'react';import { trpc } from './utils/trpc';export function App() {const [queryClient] = useState(() => new QueryClient());const [trpcClient] = useState(() =>trpc.createClient({links: [httpBatchLink({url: 'http://localhost:3000/trpc',// You can pass any HTTP headers you wish hereasync headers() {return {authorization: getAuthCookie(),};},}),],}),);return (<trpc.Provider client={trpcClient} queryClient={queryClient}><QueryClientProvider client={queryClient}>{/* Your app here */}</QueryClientProvider></trpc.Provider>);}
The reason for using useState
in the creation of the queryClient
and the TRPCClient
, as opposed to declaring them outside of the component, is to ensure that each request gets a unique client when using SSR. If you use client side rendering then you can move them if you wish.
5. Fetch data
You can now use the tRPC React Query integration to call queries and mutations on your API.
pages/IndexPage.tsxtsx
import { trpc } from '../utils/trpc';export default function IndexPage() {const userQuery= trpc.getUser.useQuery({ id: 'id_bilbo' }); const userCreator = trpc.createUser.useMutation();return (<div><p>{userQuery.data?.name}</p><button onClick={() => userCreator.mutate({ name: 'Frodo' })}> Create Frodo</button></div>);}
pages/IndexPage.tsxtsx
import { trpc } from '../utils/trpc';export default function IndexPage() {const userQuery= trpc.getUser.useQuery({ id: 'id_bilbo' }); const userCreator = trpc.createUser.useMutation();return (<div><p>{userQuery.data?.name}</p><button onClick={() => userCreator.mutate ({ name: 'Frodo' })}> Create Frodo</button></div>);}