Skip to main content
Version: 10.x

Usage with React

info
  • If you're using Next.js, read the Usage with Next.js guide instead.
  • In order to infer types from your Node.js backend, you should have the frontend and backend in the same monorepo.

Add tRPC to an existing React project​

Server Side​

1. Install dependencies​

bash
npm install @trpc/server zod
bash
npm install @trpc/server zod
Why Zod?​

Zod is an input validator to ensure that our backend only processes requests that fit our API. You can use other validation libraries like Yup, Superstruct, io-ts if you prefer. In fact, any object containing a parse, create or validateSync method will work.

2. Enable strict mode​

If you want to use Zod for input validation, make sure you have enabled strict mode in your tsconfig.json:

tsconfig.json
diff
"compilerOptions": {
+ "strict": true
}
tsconfig.json
diff
"compilerOptions": {
+ "strict": true
}

If strict mode is too harsh, at least enable strictNullChecks:

tsconfig.json
diff
"compilerOptions": {
+ "strictNullChecks": true
}
tsconfig.json
diff
"compilerOptions": {
+ "strictNullChecks": true
}

3. Implement your appRouter​

Follow the Quickstart to build your "hello world" router. Once you have your API implemented and listening via HTTP, you're ready to set up your React client.

Client Side​

tRPC works great with Create React App!

1. Install dependencies​

bash
npm install @trpc/client @trpc/server @trpc/react-query @tanstack/react-query
bash
npm install @trpc/client @trpc/server @trpc/react-query @tanstack/react-query
Why @trpc/server?​

@trpc/server is a peer dependency of @trpc/client so you will need to make sure that it is available on your client!

Why @tanstack/react-query?​

@trpc/react-query provides a thin wrapper over @tanstack/react-query. It is required as a peer dependency.

2. Create tRPC hooks​

Create a set of strongly-typed React hooks from your AppRouter type signature with createTRPCReact.

utils/trpc.ts
tsx
// utils/trpc.ts
import { createTRPCReact } from '@trpc/react-query';
import type { AppRouter } from '../path/to/router.ts';
export const trpc = createTRPCReact<AppRouter>();
utils/trpc.ts
tsx
// utils/trpc.ts
import { createTRPCReact } from '@trpc/react-query';
import type { AppRouter } from '../path/to/router.ts';
export const trpc = createTRPCReact<AppRouter>();

3. Add tRPC providers​

App.tsx
tsx
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:5000/trpc',
// optional
headers() {
return {
authorization: getAuthCookie(),
};
},
}),
],
}),
);
return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
{/* Your app here */}
</QueryClientProvider>
</trpc.Provider>
);
}
App.tsx
tsx
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:5000/trpc',
// optional
headers() {
return {
authorization: getAuthCookie(),
};
},
}),
],
}),
);
return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
{/* Your app here */}
</QueryClientProvider>
</trpc.Provider>
);
}

4. Fetch data​

pages/IndexPage.tsx
tsx
import { trpc } from '../utils/trpc';
export default function IndexPage() {
const hello = trpc.hello.useQuery({ text: 'client' });
if (!hello.data) return <div>Loading...</div>;
return (
<div>
<p>{hello.data.greeting}</p>
</div>
);
}
pages/IndexPage.tsx
tsx
import { trpc } from '../utils/trpc';
export default function IndexPage() {
const hello = trpc.hello.useQuery({ text: 'client' });
if (!hello.data) return <div>Loading...</div>;
return (
<div>
<p>{hello.data.greeting}</p>
</div>
);
}