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
bash
yarn add @trpc/server zod
bash
yarn add @trpc/server zod
- 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
orvalidateSync
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
:
json
// tsconfig.json{// ..."compilerOptions": {// ..."strict": true}}
json
// tsconfig.json{// ..."compilerOptions": {// ..."strict": true}}
If strict mode is too much, at least enable strictNullChecks
:
json
// tsconfig.json{// ..."compilerOptions": {// ..."strictNullChecks": true}}
json
// tsconfig.json{// ..."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
bash
yarn add @trpc/client @trpc/server @trpc/react react-query@3
bash
yarn add @trpc/client @trpc/server @trpc/react react-query@3
- @trpc/server: This is a peer dependency of
@trpc/client
so you have to install it again! - Tanstack's 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.tstsx
// utils/trpc.tsimport { createReactQueryHooks } from '@trpc/react';import type { AppRouter } from '../path/to/router.ts';export const trpc = createReactQueryHooks<AppRouter>();// => { useQuery: ..., useMutation: ...}
utils/trpc.tstsx
// utils/trpc.tsimport { createReactQueryHooks } from '@trpc/react';import type { AppRouter } from '../path/to/router.ts';export const trpc = createReactQueryHooks<AppRouter>();// => { useQuery: ..., useMutation: ...}
3. Add tRPC providers
In your App.tsx
App.tsxtsx
import React from 'react';import { useState } from 'react';import { QueryClient, QueryClientProvider } from 'react-query';import { trpc } from './utils/trpc';export function App() {const [queryClient] = useState(() => new QueryClient());const [trpcClient] = useState(() =>trpc.createClient({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 React from 'react';import { useState } from 'react';import { QueryClient, QueryClientProvider } from 'react-query';import { trpc } from './utils/trpc';export function App() {const [queryClient] = useState(() => new QueryClient());const [trpcClient] = useState(() =>trpc.createClient({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>);}
4. Fetch data
pages/IndexPage.tsxtsx
import { trpc } from '../utils/trpc';export default function IndexPage() {const hello = trpc.useQuery(['hello', { 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.useQuery(['hello', { text: 'client' }]);if (!hello.data) return <div>Loading...</div>;return (<div><p>{hello.data.greeting}</p></div>);}