TanStack React Query
与我们的 经典 React 查询集成 相比,此客户端更简单且更 TanStack Query 原生,为常见的 TanStack React Query 接口(如 QueryKeys、QueryOptions 和 MutationOptions)提供工厂。我们认为这是未来,并建议使用它而不是经典客户端 read the announcement post 来了解有关此更改的更多信息。
¥Compared to our classic React Query Integration this client is simpler and more TanStack Query-native, providing factories for common TanStack React Query interfaces like QueryKeys, QueryOptions, and MutationOptions. We think it's the future and recommend using this over the classic client, read the announcement post for more information about this change.
你可以在 tRPC.io 的主页上尝试此集成:[https://trpc.nodejs.cn/?try=minimal-react#try-it-out](/?try=minimal-react#try-it-out)
¥You can try this integration out on the homepage of tRPC.io: https://trpc.nodejs.cn/?try=minimal-react#try-it-out
❓ Do I have to use an integration?
No! The integration is fully optional. You can use @tanstack/react-query
using just a vanilla tRPC client, although then you'll have to manually manage query keys and do not get the same level of DX as when using the integration package.
utils/trpc.tsts
export const trpc = createTRPCClient<AppRouter>({links: [httpBatchLink({ url: 'YOUR_API_URL' })],});
utils/trpc.tsts
export const trpc = createTRPCClient<AppRouter>({links: [httpBatchLink({ url: 'YOUR_API_URL' })],});
components/PostList.tsxtsx
function PostList() {const { data } = useQuery({queryKey: ['posts'],queryFn: () => trpc.post.list.query(),});data; // Post[]// ...}
components/PostList.tsxtsx
function PostList() {const { data } = useQuery({queryKey: ['posts'],queryFn: () => trpc.post.list.query(),});data; // Post[]// ...}
设置
¥Setup
1. 安装依赖
¥ Install dependencies
应安装以下依赖
¥The following dependencies should be installed
- npm
- yarn
- pnpm
- bun
- deno
npm install @trpc/server @trpc/client @trpc/tanstack-react-query @tanstack/react-query
yarn add @trpc/server @trpc/client @trpc/tanstack-react-query @tanstack/react-query
pnpm add @trpc/server @trpc/client @trpc/tanstack-react-query @tanstack/react-query
bun add @trpc/server @trpc/client @trpc/tanstack-react-query @tanstack/react-query
deno add npm:@trpc/server npm:@trpc/client npm:@trpc/tanstack-react-query npm:@tanstack/react-query
2. 导入你的 AppRouter
¥ Import your AppRouter
将 AppRouter
类型导入客户端应用。这种类型保存了整个 API 的形状。
¥Import your AppRouter
type into the client application. This type holds the shape of your entire API.
utils/trpc.tsts
import type {AppRouter } from '../server/router';
utils/trpc.tsts
import type {AppRouter } from '../server/router';
通过使用 import type
,你可以确保在编译时删除引用,这意味着你不会无意中将服务器端代码导入到客户端中。欲了解更多信息,请参阅 Typescript 文档。
¥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.
3a.设置 tRPC 上下文提供程序
¥3a. Setup the tRPC context provider
在依赖 React 上下文的情况下,例如在 Next.js 等全栈框架中使用服务器端渲染时,为每个请求创建一个新的 QueryClient 很重要,这样你的用户就不会共享相同的缓存,你可以使用 createTRPCContext
从你的 AppRouter
类型签名创建一组类型安全的上下文提供程序和消费者。
¥In cases where you rely on React context, such as when using server-side rendering in full-stack frameworks like Next.js, it's important to create a new QueryClient for each request so that your users don't end up sharing the same cache, you can use the createTRPCContext
to create a set of type-safe context providers and consumers from your AppRouter
type signature.
utils/trpc.tstsx
import {createTRPCContext } from '@trpc/tanstack-react-query';import type {AppRouter } from '../server/router';export const {TRPCProvider ,useTRPC ,useTRPCClient } =createTRPCContext <AppRouter >();
utils/trpc.tstsx
import {createTRPCContext } from '@trpc/tanstack-react-query';import type {AppRouter } from '../server/router';export const {TRPCProvider ,useTRPC ,useTRPCClient } =createTRPCContext <AppRouter >();
然后,创建一个 tRPC 客户端,并将你的应用封装在 TRPCProvider
中,如下所示。你还需要设置并连接 React Query,即 他们更深入地记录。
¥Then, create a tRPC client, and wrap your application in the TRPCProvider
, as below. You will also need to set up and connect React Query, which they document in more depth.
如果你已经在应用中使用 React Query,则应该重新使用已有的 QueryClient
和 QueryClientProvider
。你可以在 React Query 文档 中阅读有关 QueryClient 初始化的更多信息。
¥If you already use React Query in your application, you should re-use the QueryClient
and QueryClientProvider
you already have. You can read more about the QueryClient initialization in the React Query docs.
components/App.tsxtsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';import { createTRPCClient, httpBatchLink } from '@trpc/client';import { useState } from 'react';import { TRPCProvider } from './utils/trpc';function makeQueryClient() {return new QueryClient({defaultOptions: {queries: {// With SSR, we usually want to set some default staleTime// above 0 to avoid refetching immediately on the clientstaleTime: 60 * 1000,},},});}let browserQueryClient: QueryClient | undefined = undefined;function getQueryClient() {if (typeof window === 'undefined') {// Server: always make a new query clientreturn makeQueryClient();} else {// Browser: make a new query client if we don't already have one// This is very important, so we don't re-make a new client if React// suspends during the initial render. This may not be needed if we// have a suspense boundary BELOW the creation of the query clientif (!browserQueryClient) browserQueryClient = makeQueryClient();return browserQueryClient;}}export function App() {const queryClient = getQueryClient();const [trpcClient] = useState(() =>createTRPCClient<AppRouter>({links: [httpBatchLink({url: 'http://localhost:2022',}),],}),);return (<QueryClientProvider client={queryClient}><TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>{/* Your app here */}</TRPCProvider></QueryClientProvider>);}
components/App.tsxtsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';import { createTRPCClient, httpBatchLink } from '@trpc/client';import { useState } from 'react';import { TRPCProvider } from './utils/trpc';function makeQueryClient() {return new QueryClient({defaultOptions: {queries: {// With SSR, we usually want to set some default staleTime// above 0 to avoid refetching immediately on the clientstaleTime: 60 * 1000,},},});}let browserQueryClient: QueryClient | undefined = undefined;function getQueryClient() {if (typeof window === 'undefined') {// Server: always make a new query clientreturn makeQueryClient();} else {// Browser: make a new query client if we don't already have one// This is very important, so we don't re-make a new client if React// suspends during the initial render. This may not be needed if we// have a suspense boundary BELOW the creation of the query clientif (!browserQueryClient) browserQueryClient = makeQueryClient();return browserQueryClient;}}export function App() {const queryClient = getQueryClient();const [trpcClient] = useState(() =>createTRPCClient<AppRouter>({links: [httpBatchLink({url: 'http://localhost:2022',}),],}),);return (<QueryClientProvider client={queryClient}><TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>{/* Your app here */}</TRPCProvider></QueryClientProvider>);}
3b.不使用 React 上下文进行设置
¥3b. Setup without React context
当仅使用 Vite 之类的客户端渲染构建 SPA 时,你可以在 React 上下文之外创建 QueryClient
和 tRPC 客户端作为单例。
¥When building an SPA using only client-side rendering with something like Vite, you can create the QueryClient
and tRPC client outside of React context as singletons.
utils/trpc.tsts
import { QueryClient } from '@tanstack/react-query';import { createTRPCClient, httpBatchLink } from '@trpc/client';import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query';import type { AppRouter } from '../server/router';export const queryClient = new QueryClient();const trpcClient = createTRPCClient<AppRouter>({links: [httpBatchLink({ url: 'http://localhost:2022' })],});export const trpc = createTRPCOptionsProxy<AppRouter>({client: trpcClient,queryClient,});
utils/trpc.tsts
import { QueryClient } from '@tanstack/react-query';import { createTRPCClient, httpBatchLink } from '@trpc/client';import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query';import type { AppRouter } from '../server/router';export const queryClient = new QueryClient();const trpcClient = createTRPCClient<AppRouter>({links: [httpBatchLink({ url: 'http://localhost:2022' })],});export const trpc = createTRPCOptionsProxy<AppRouter>({client: trpcClient,queryClient,});
components/App.tsxtsx
import { QueryClientProvider } from '@tanstack/react-query';import React from 'react';import { queryClient } from './utils/trpc';export function App() {return (<QueryClientProvider client={queryClient}>{/* Your app here */}</QueryClientProvider>);}
components/App.tsxtsx
import { QueryClientProvider } from '@tanstack/react-query';import React from 'react';import { queryClient } from './utils/trpc';export function App() {return (<QueryClientProvider client={queryClient}>{/* Your app here */}</QueryClientProvider>);}
4. 获取数据
¥ Fetch data
你现在可以使用 tRPC React Query 集成来调用 API 上的查询和变更。
¥You can now use the tRPC React Query integration to call queries and mutations on your API.
components/user-list.tsxtsx
import { useMutation, useQuery } from '@tanstack/react-query';import { useTRPC } from '../utils/trpc';export default function UserList() {const trpc = useTRPC(); // use `import { trpc } from './utils/trpc'` if you're using the singleton patternconst userQuery = useQuery(trpc.getUser.queryOptions({ id: 'id_bilbo' }));const userCreator = useMutation(trpc.createUser.mutationOptions());return (<div><p>{userQuery.data?.name}</p><button onClick={() => userCreator.mutate({ name: 'Frodo' })}>Create Frodo</button></div>);}
components/user-list.tsxtsx
import { useMutation, useQuery } from '@tanstack/react-query';import { useTRPC } from '../utils/trpc';export default function UserList() {const trpc = useTRPC(); // use `import { trpc } from './utils/trpc'` if you're using the singleton patternconst userQuery = useQuery(trpc.getUser.queryOptions({ id: 'id_bilbo' }));const userCreator = useMutation(trpc.createUser.mutationOptions());return (<div><p>{userQuery.data?.name}</p><button onClick={() => userCreator.mutate({ name: 'Frodo' })}>Create Frodo</button></div>);}