Usage with React
- 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
- npm
- yarn
- pnpm
bash
npm install @trpc/server zod
bash
npm install @trpc/server zod
bash
yarn add @trpc/server zod
bash
yarn add @trpc/server zod
bash
pnpm add @trpc/server zod
bash
pnpm add @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.jsondiff
"compilerOptions": {+ "strict": true}
tsconfig.jsondiff
"compilerOptions": {+ "strict": true}
If strict mode is too harsh, at least enable strictNullChecks
:
tsconfig.jsondiff
"compilerOptions": {+ "strictNullChecks": true}
tsconfig.jsondiff
"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
- npm
- yarn
- pnpm
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
bash
yarn add @trpc/client @trpc/server @trpc/react-query @tanstack/react-query
bash
yarn add @trpc/client @trpc/server @trpc/react-query @tanstack/react-query
bash
pnpm add @trpc/client @trpc/server @trpc/react-query @tanstack/react-query
bash
pnpm add @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.tstsx
// utils/trpc.tsimport { createTRPCReact } from '@trpc/react-query';import type { AppRouter } from '../path/to/router.ts';export const trpc = createTRPCReact<AppRouter>();
utils/trpc.tstsx
// utils/trpc.tsimport { createTRPCReact } from '@trpc/react-query';import type { AppRouter } from '../path/to/router.ts';export const trpc = createTRPCReact<AppRouter>();
3. Add tRPC providers
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:5000/trpc',// optionalheaders() {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:5000/trpc',// optionalheaders() {return {authorization: getAuthCookie(),};},}),],}),);return (<trpc.Provider client={trpcClient} queryClient={queryClient}><QueryClientProvider client={queryClient}>{/* Your app here */}</QueryClientProvider></trpc.Provider>);}
The reason behind the useState
calls for the creation of the queryClient
and the TRPCClient
in the example above as opposed to declaring them outside of the component is to ensure that each request gets a unique client while using SSR so that request caches aren't shared between them.
4. Fetch data
pages/IndexPage.tsxtsx
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.tsxtsx
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>);}