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 & backend in the same monorepo.

Add tRPC to existing React project

Server Side

1. Install dependencies

npm

bash
npm install @trpc/server@next zod
bash
npm install @trpc/server@next zod

yarn

bash
yarn add @trpc/server@next zod
bash
yarn add @trpc/server@next zod

pnpm

bash
pnpm add @trpc/server@next zod
bash
pnpm add @trpc/server@next zod
Why Zod?

Most examples use Zod for input validation and we highly recommended it, though it isn't required. You can use a validation library of your choice (Yup, Superstruct, io-ts, etc). 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 much, at least enable strictNullChecks:

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

3. Implement your appRouter

Follow the Quickstart and read the @trpc/server docs for guidance on this. Once you have your API implemented and listening via HTTP, continue to the next step.

Client Side

tRPC works fine with Create React App!

1. Install dependencies

npm

bash
npm install @trpc/client@next @trpc/server@next @trpc/react@next @tanstack/react-query
bash
npm install @trpc/client@next @trpc/server@next @trpc/react@next @tanstack/react-query

yarn

bash
yarn add @trpc/client@next @trpc/server@next @trpc/react@next @tanstack/react-query
bash
yarn add @trpc/client@next @trpc/server@next @trpc/react@next @tanstack/react-query

pnpm

bash
pnpm add @trpc/client@next @trpc/server@next @trpc/react@next @tanstack/react-query
bash
pnpm add @trpc/client@next @trpc/server@next @trpc/react@next @tanstack/react-query
Why @trpc/server?

This is a peer dependency of @trpc/client so you have to install it again!

Why @tanstack/react-query?

@trpc/react 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 createReactQueryHooks.

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

3. Add tRPC providers

App.tsx
tsx
import React, { useState } from 'react';
import { httpBatchLink } from '@trpc/client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
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 React, { useState } from 'react';
import { httpBatchLink } from '@trpc/client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
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>
);
}