TanStack React Query
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
快速查询示例
tsximport {useQuery } from '@tanstack/react-query';import {useTRPC } from './trpc';functionUsers () {consttrpc =useTRPC ();constgreetingQuery =useQuery (trpc .greeting .queryOptions ({name : 'Jerry' }));// greetingQuery.data === 'Hello Jerry'}
tsximport {useQuery } from '@tanstack/react-query';import {useTRPC } from './trpc';functionUsers () {consttrpc =useTRPC ();constgreetingQuery =useQuery (trpc .greeting .queryOptions ({name : 'Jerry' }));// greetingQuery.data === 'Hello Jerry'}
用法
该客户端的设计理念是提供轻量级且类型安全的工厂方法,与 Tanstack React Query 原生无缝集成。这意味着只需跟随客户端提供的自动补全提示,您就能专注于开发工作,所需知识完全遵循 TanStack React Query 官方文档的内容。
tsxexport default functionBasics () {consttrpc =useTRPC ();constqueryClient =useQueryClient ();// Create QueryOptions which can be passed to query hooksconstmyQueryOptions =trpc .path .to .query .queryOptions ({ /** inputs */ })constmyQuery =useQuery (myQueryOptions )// or:// useSuspenseQuery(myQueryOptions)// useInfiniteQuery(myQueryOptions)// Create MutationOptions which can be passed to useMutationconstmyMutationOptions =trpc .path .to .mutation .mutationOptions ()constmyMutation =useMutation (myMutationOptions )// Create a QueryKey which can be used to manipulate many methods// on TanStack's QueryClient in a type-safe mannerconstmyQueryKey =trpc .path .to .query .queryKey ()constinvalidateMyQueryKey = () => {queryClient .invalidateQueries ({queryKey :myQueryKey })}return (// Your app herenull)}
tsxexport default functionBasics () {consttrpc =useTRPC ();constqueryClient =useQueryClient ();// Create QueryOptions which can be passed to query hooksconstmyQueryOptions =trpc .path .to .query .queryOptions ({ /** inputs */ })constmyQuery =useQuery (myQueryOptions )// or:// useSuspenseQuery(myQueryOptions)// useInfiniteQuery(myQueryOptions)// Create MutationOptions which can be passed to useMutationconstmyMutationOptions =trpc .path .to .mutation .mutationOptions ()constmyMutation =useMutation (myMutationOptions )// Create a QueryKey which can be used to manipulate many methods// on TanStack's QueryClient in a type-safe mannerconstmyQueryKey =trpc .path .to .query .queryKey ()constinvalidateMyQueryKey = () => {queryClient .invalidateQueries ({queryKey :myQueryKey })}return (// Your app herenull)}
trpc 对象具备完整的类型安全特性,可为 AppRouter 中的所有过程提供自动补全。在代理链末端,以下方法可供使用:
queryOptions - 数据查询
适用于所有查询过程。提供对 Tanstack 的 queryOptions 函数的类型安全封装。第一个参数是过程的输入值,第二个参数接受所有原生 Tanstack React Query 配置选项。
tsconstqueryOptions =trpc .path .to .query .queryOptions ({/** input */id : 'foo',},{// Any Tanstack React Query optionsstaleTime : 1000,},);
tsconstqueryOptions =trpc .path .to .query .queryOptions ({/** input */id : 'foo',},{// Any Tanstack React Query optionsstaleTime : 1000,},);
您还可以向 queryOptions 函数传递 trpc 对象,从而为客户端提供 tRPC 请求配置选项。
tsconstqueryOptions =trpc .path .to .query .queryOptions ({/** input */id : 'foo',},{trpc : {// Provide tRPC request options to the clientcontext : {// see https://trpc.io/docs/client/links#managing-context},},},);
tsconstqueryOptions =trpc .path .to .query .queryOptions ({/** input */id : 'foo',},{trpc : {// Provide tRPC request options to the clientcontext : {// see https://trpc.io/docs/client/links#managing-context},},},);
若需要以类型安全的方式禁用查询,可使用 skipToken:
tsconstquery =useQuery (trpc .user .details .queryOptions (user ?.id &&project ?.id ? {userId :user .id ,projectId :project .id ,}:skipToken ,{staleTime : 1000,},),);
tsconstquery =useQuery (trpc .user .details .queryOptions (user ?.id &&project ?.id ? {userId :user .id ,projectId :project .id ,}:skipToken ,{staleTime : 1000,},),);
返回结果可传递给 useQuery 或 useSuspenseQuery 钩子,亦或是查询客户端方法如 fetchQuery、prefetchQuery、prefetchInfiniteQuery、invalidateQueries 等。
infiniteQueryOptions - 无限数据查询
适用于所有接收游标输入的查询过程。提供对 Tanstack 的 infiniteQueryOptions 函数的类型安全封装。第一个参数是过程的输入值,第二个参数接受所有原生 Tanstack React Query 配置选项。
tsconstinfiniteQueryOptions =trpc .path .to .query .infiniteQueryOptions ({/** input */},{// Any Tanstack React Query optionsgetNextPageParam : (lastPage ,pages ) =>lastPage .nextCursor ,},);
tsconstinfiniteQueryOptions =trpc .path .to .query .infiniteQueryOptions ({/** input */},{// Any Tanstack React Query optionsgetNextPageParam : (lastPage ,pages ) =>lastPage .nextCursor ,},);
queryKey - 获取查询键及执行查询客户端操作
适用于所有查询过程。允许以类型安全的方式访问查询键。
tsconstqueryKey =trpc .path .to .query .queryKey ();
tsconstqueryKey =trpc .path .to .query .queryKey ();
由于 Tanstack React Query 对查询键使用模糊匹配,您还可以创建任意子路径的部分查询键,以匹配属于特定路由器的所有查询:
tsconstqueryKey =trpc .router .pathKey ();
tsconstqueryKey =trpc .router .pathKey ();
甚至可以使用根路径匹配所有 tRPC 查询:
tsconstqueryKey =trpc .pathKey ();
tsconstqueryKey =trpc .pathKey ();
infiniteQueryKey - 获取无限查询键
适用于所有接收游标输入的查询过程。允许以类型安全的方式访问无限查询的查询键。
tsconstinfiniteQueryKey =trpc .path .to .query .infiniteQueryKey ({/** input */});
tsconstinfiniteQueryKey =trpc .path .to .query .infiniteQueryKey ({/** input */});
返回结果可用于查询客户端方法,如 getQueryData、setQueryData、invalidateQueries 等。
ts// Get cached data for an infinite queryconstcachedData =queryClient .getQueryData (trpc .path .to .query .infiniteQueryKey ({cursor : 0 }),);// Set cached data for an infinite queryqueryClient .setQueryData (trpc .path .to .query .infiniteQueryKey ({cursor : 0 }),(data ) => {// Modify the datareturndata ;},);
ts// Get cached data for an infinite queryconstcachedData =queryClient .getQueryData (trpc .path .to .query .infiniteQueryKey ({cursor : 0 }),);// Set cached data for an infinite queryqueryClient .setQueryData (trpc .path .to .query .infiniteQueryKey ({cursor : 0 }),(data ) => {// Modify the datareturndata ;},);
queryFilter - 创建查询过滤器
适用于所有查询过程。允许以类型安全的方式创建 查询过滤器。
tsconstqueryFilter =trpc .path .to .query .queryFilter ({/** input */},{// Any Tanstack React Query filterpredicate : (query ) => {return !!query .state .data ;},},);
tsconstqueryFilter =trpc .path .to .query .queryFilter ({/** input */},{// Any Tanstack React Query filterpredicate : (query ) => {return !!query .state .data ;},},);
与查询键类似,若需在整个路由器范围执行过滤操作,可使用 pathFilter 来定位任意子路径。
tsconstqueryFilter =trpc .path .pathFilter ({// Any Tanstack React Query filterpredicate : (query ) => {return !!query .state .data ;},});
tsconstqueryFilter =trpc .path .pathFilter ({// Any Tanstack React Query filterpredicate : (query ) => {return !!query .state .data ;},});
此方法适用于创建可传递给客户端方法(如 queryClient.invalidateQueries 等)的过滤器。
infiniteQueryFilter - 创建无限查询过滤器
适用于所有接收游标输入的查询过程。允许以类型安全的方式为无限查询创建 查询过滤器。
tsconstinfiniteQueryFilter =trpc .path .to .query .infiniteQueryFilter ({/** input */},{// Any Tanstack React Query filterpredicate : (query ) => {return !!query .state .data ;},},);
tsconstinfiniteQueryFilter =trpc .path .to .query .infiniteQueryFilter ({/** input */},{// Any Tanstack React Query filterpredicate : (query ) => {return !!query .state .data ;},},);
此方法适用于创建可传递给客户端方法(如 queryClient.invalidateQueries 等)的过滤器。
tsawaitqueryClient .invalidateQueries (trpc .path .to .query .infiniteQueryFilter ({},{predicate : (query ) => {// Filter logic based on query statereturnquery .state .status === 'success';},},),);
tsawaitqueryClient .invalidateQueries (trpc .path .to .query .infiniteQueryFilter ({},{predicate : (query ) => {// Filter logic based on query statereturnquery .state .status === 'success';},},),);
mutationOptions - 创建变更配置
适用于所有变更过程。提供类型安全的恒等函数,用于构建可传递给 useMutation 的配置选项。
tsconstmutationOptions =trpc .path .to .mutation .mutationOptions ({// Any Tanstack React Query optionsonSuccess : (data ) => {// do something with the data},});
tsconstmutationOptions =trpc .path .to .mutation .mutationOptions ({// Any Tanstack React Query optionsonSuccess : (data ) => {// do something with the data},});
mutationKey - 获取变更键
适用于所有变更过程。允许以类型安全的方式获取变更键。
tsconstmutationKey =trpc .path .to .mutation .mutationKey ();
tsconstmutationKey =trpc .path .to .mutation .mutationKey ();
subscriptionOptions - 创建订阅配置
由于 TanStack 未提供订阅钩子,因此我们在此继续提供自有的抽象层,该抽象层与 标准 tRPC 订阅配置 协同工作。
适用于所有订阅过程。提供类型安全的恒等函数,用于构建可传递给 useSubscription 的配置选项。
请注意,您需要在 tRPC 客户端中配置 httpSubscriptionLink 或 wsLink 方可使用订阅功能。
tsxfunctionSubscriptionExample () {consttrpc =useTRPC ();constsubscription =useSubscription (trpc .path .to .subscription .subscriptionOptions ({/** input */},{enabled : true,onStarted : () => {// do something when the subscription is started},onData : (data ) => {// you can handle the data here},onError : (error ) => {// you can handle the error here},onConnectionStateChange : (state ) => {// you can handle the connection state here},},),);// Or you can handle the state heresubscription .data ; // The lastly received datasubscription .error ; // The lastly received error/*** The current status of the subscription.* Will be one of: `'idle'`, `'connecting'`, `'pending'`, or `'error'`.** - `idle`: subscription is disabled or ended* - `connecting`: trying to establish a connection* - `pending`: connected to the server, receiving data* - `error`: an error occurred and the subscription is stopped*/subscription .status ;// Reset the subscription (if you have an error etc)subscription .reset ();return <>{/* ... */}</>;}
tsxfunctionSubscriptionExample () {consttrpc =useTRPC ();constsubscription =useSubscription (trpc .path .to .subscription .subscriptionOptions ({/** input */},{enabled : true,onStarted : () => {// do something when the subscription is started},onData : (data ) => {// you can handle the data here},onError : (error ) => {// you can handle the error here},onConnectionStateChange : (state ) => {// you can handle the connection state here},},),);// Or you can handle the state heresubscription .data ; // The lastly received datasubscription .error ; // The lastly received error/*** The current status of the subscription.* Will be one of: `'idle'`, `'connecting'`, `'pending'`, or `'error'`.** - `idle`: subscription is disabled or ended* - `connecting`: trying to establish a connection* - `pending`: connected to the server, receiving data* - `error`: an error occurred and the subscription is stopped*/subscription .status ;// Reset the subscription (if you have an error etc)subscription .reset ();return <>{/* ... */}</>;}
查询键前缀
当在单个应用中使用多个 tRPC 提供程序时(例如连接不同的后端服务),相同路径的查询会在缓存中发生冲突。启用查询键前缀功能可避免此问题。
tsx// Without prefixes - these would collide!constauthQuery =useQuery (trpcAuth .list .queryOptions ()); // auth serviceconstbillingQuery =useQuery (trpcBilling .list .queryOptions ()); // billing service
tsx// Without prefixes - these would collide!constauthQuery =useQuery (trpcAuth .list .queryOptions ()); // auth serviceconstbillingQuery =useQuery (trpcBilling .list .queryOptions ()); // billing service
在创建上下文时启用功能标志:
utils/trpc.tstsx// [...]constbilling =createTRPCContext <BillingRouter , {keyPrefix : true }>();export constBillingProvider =billing .TRPCProvider ;export constuseBilling =billing .useTRPC ;export constcreateBillingClient = () =>createTRPCClient <BillingRouter >({links : [/* ... */],});constaccount =createTRPCContext <AccountRouter , {keyPrefix : true }>();export constAccountProvider =account .TRPCProvider ;export constuseAccount =account .useTRPC ;export constcreateAccountClient = () =>createTRPCClient <AccountRouter >({links : [/* ... */],});
utils/trpc.tstsx// [...]constbilling =createTRPCContext <BillingRouter , {keyPrefix : true }>();export constBillingProvider =billing .TRPCProvider ;export constuseBilling =billing .useTRPC ;export constcreateBillingClient = () =>createTRPCClient <BillingRouter >({links : [/* ... */],});constaccount =createTRPCContext <AccountRouter , {keyPrefix : true }>();export constAccountProvider =account .TRPCProvider ;export constuseAccount =account .useTRPC ;export constcreateAccountClient = () =>createTRPCClient <AccountRouter >({links : [/* ... */],});
App.tsxtsximport {useState } from 'react';import {QueryClient ,QueryClientProvider } from '@tanstack/react-query';import {BillingProvider ,AccountProvider ,createBillingClient ,createAccountClient ,} from './utils/trpc';// [...]export functionApp () {const [queryClient ] =useState (() => newQueryClient ());const [billingClient ] =useState (() =>createBillingClient ());const [accountClient ] =useState (() =>createAccountClient ());return (<QueryClientProvider client ={queryClient }><BillingProvider trpcClient ={billingClient }queryClient ={queryClient }keyPrefix ="billing"><AccountProvider trpcClient ={accountClient }queryClient ={queryClient }keyPrefix ="account"><div >{/* ... */}</div ></AccountProvider ></BillingProvider ></QueryClientProvider >);}
App.tsxtsximport {useState } from 'react';import {QueryClient ,QueryClientProvider } from '@tanstack/react-query';import {BillingProvider ,AccountProvider ,createBillingClient ,createAccountClient ,} from './utils/trpc';// [...]export functionApp () {const [queryClient ] =useState (() => newQueryClient ());const [billingClient ] =useState (() =>createBillingClient ());const [accountClient ] =useState (() =>createAccountClient ());return (<QueryClientProvider client ={queryClient }><BillingProvider trpcClient ={billingClient }queryClient ={queryClient }keyPrefix ="billing"><AccountProvider trpcClient ={accountClient }queryClient ={queryClient }keyPrefix ="account"><div >{/* ... */}</div ></AccountProvider ></BillingProvider ></QueryClientProvider >);}
components/MyComponent.tsxtsximport {useQuery } from '@tanstack/react-query';import {useBilling ,useAccount } from '../utils/trpc';// [...]export functionMyComponent () {constbilling =useBilling ();constaccount =useAccount ();constbillingList =useQuery (billing .list .queryOptions ());constaccountList =useQuery (account .list .queryOptions ());return (<div ><div >Billing: {JSON .stringify (billingList .data ?? null)}</div ><div >Account: {JSON .stringify (accountList .data ?? null)}</div ></div >);}
components/MyComponent.tsxtsximport {useQuery } from '@tanstack/react-query';import {useBilling ,useAccount } from '../utils/trpc';// [...]export functionMyComponent () {constbilling =useBilling ();constaccount =useAccount ();constbillingList =useQuery (billing .list .queryOptions ());constaccountList =useQuery (account .list .queryOptions ());return (<div ><div >Billing: {JSON .stringify (billingList .data ?? null)}</div ><div >Account: {JSON .stringify (accountList .data ?? null)}</div ></div >);}
查询键将被正确添加前缀以避免冲突:
tsx// Example of how the query keys look with prefixesconstqueryKeys = [[['billing'], ['list'], {type : 'query' }],[['account'], ['list'], {type : 'query' }],];
tsx// Example of how the query keys look with prefixesconstqueryKeys = [[['billing'], ['list'], {type : 'query' }],[['account'], ['list'], {type : 'query' }],];
推断输入输出类型
当需要推断过程或路由器的输入输出类型时,根据场景提供两种方案:
推断整个路由器的输入输出类型
tsimport type {inferRouterInputs ,inferRouterOutputs } from '@trpc/server';import type {AppRouter } from './server/router';export typeInputs =inferRouterInputs <AppRouter >;export typeOutputs =inferRouterOutputs <AppRouter >;
tsimport type {inferRouterInputs ,inferRouterOutputs } from '@trpc/server';import type {AppRouter } from './server/router';export typeInputs =inferRouterInputs <AppRouter >;export typeOutputs =inferRouterOutputs <AppRouter >;
推断单个过程的类型
tsimport type {inferInput ,inferOutput } from '@trpc/tanstack-react-query';functionComponent () {consttrpc =useTRPC ();typeInput =inferInput <typeoftrpc .path .to .procedure >;typeOutput =inferOutput <typeoftrpc .path .to .procedure >;}
tsimport type {inferInput ,inferOutput } from '@trpc/tanstack-react-query';functionComponent () {consttrpc =useTRPC ();typeInput =inferInput <typeoftrpc .path .to .procedure >;typeOutput =inferOutput <typeoftrpc .path .to .procedure >;}
访问 tRPC 客户端
若您采用 基于 React Context 的配置方案,可通过 useTRPCClient 钩子访问 tRPC 客户端。
tsximport {useTRPCClient } from './trpc';async functionComponent () {consttrpcClient =useTRPCClient ();constresult = awaittrpcClient .getUser .query ({id : '1',});}
tsximport {useTRPCClient } from './trpc';async functionComponent () {consttrpcClient =useTRPCClient ();constresult = awaittrpcClient .getUser .query ({id : '1',});}
若您采用 无 React Context 的配置方案,则可直接导入全局客户端实例。
tsimport {client } from './trpc';constresult = awaitclient .path .to .procedure .query ({/** input */id : 'foo',});
tsimport {client } from './trpc';constresult = awaitclient .path .to .procedure .query ({/** input */id : 'foo',});