useQuery()
非官方测试版翻译
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
useQuery 是数据获取的核心钩子,其工作方式类似于 @tanstack/react-query 的 useQuery,但包含一些 trpc 特有的选项和附加功能(如流式传输)。
备注
有关选项和使用模式的详细信息,请参阅 TanStack Query 文档中的查询指南。
函数签名
tsxfunction useQuery(input: TInput | SkipToken,opts?: UseTRPCQueryOptions;)interface UseTRPCQueryOptionsextends UseQueryOptions {trpc: {ssr?: boolean;abortOnUnmount?: boolean;context?: Record<string, unknown>;}}
tsxfunction useQuery(input: TInput | SkipToken,opts?: UseTRPCQueryOptions;)interface UseTRPCQueryOptionsextends UseQueryOptions {trpc: {ssr?: boolean;abortOnUnmount?: boolean;context?: Record<string, unknown>;}}
由于 UseTRPCQueryOptions 继承自 @tanstack/react-query 的 UseQueryOptions,你可以使用其所有选项(如 enabled、refetchOnWindowFocus 等)。此外,我们还提供了一些 trpc 特有选项,允许你在单个过程级别启用或禁用特定行为:
-
trpc.ssr: 当全局配置中设置了ssr: true时,可通过此选项设为 false 来禁用当前查询的 SSR 功能。注意:反向操作无效,即全局配置为 false 时无法为单个过程启用 SSR -
trpc.abortOnUnmount: 覆盖全局配置,控制组件卸载时是否中止查询 -
trpc.context: 添加可在链接中使用的额外元数据
技巧
如需设置选项但无需传递输入参数,可传入 undefined
你会注意到 input 的自动补全功能完全基于后端定义的 input 结构
用法示例
Backend code
server/routers/_app.tstsximport { initTRPC } from '@trpc/server';import { z } from 'zod';export const t = initTRPC.create();export const appRouter = t.router({// Create procedure at path 'hello'hello: t.procedure// using zod schema to validate and infer input values.input(z.object({text: z.string().nullish(),}).nullish(),).query((opts) => {return {greeting: `hello ${opts.input?.text ?? 'world'}`,};}),});
server/routers/_app.tstsximport { initTRPC } from '@trpc/server';import { z } from 'zod';export const t = initTRPC.create();export const appRouter = t.router({// Create procedure at path 'hello'hello: t.procedure// using zod schema to validate and infer input values.input(z.object({text: z.string().nullish(),}).nullish(),).query((opts) => {return {greeting: `hello ${opts.input?.text ?? 'world'}`,};}),});
components/MyComponent.tsxtsximport { trpc } from '../utils/trpc';export function MyComponent() {// input is optional, so we don't have to pass second argumentconst helloNoArgs = trpc.hello.useQuery();const helloWithArgs = trpc.hello.useQuery({ text: 'client' });return (<div><h1>Hello World Example</h1><ul><li>helloNoArgs ({helloNoArgs.status}):{' '}<pre>{JSON.stringify(helloNoArgs.data, null, 2)}</pre></li><li>helloWithArgs ({helloWithArgs.status}):{' '}<pre>{JSON.stringify(helloWithArgs.data, null, 2)}</pre></li></ul></div>);}
components/MyComponent.tsxtsximport { trpc } from '../utils/trpc';export function MyComponent() {// input is optional, so we don't have to pass second argumentconst helloNoArgs = trpc.hello.useQuery();const helloWithArgs = trpc.hello.useQuery({ text: 'client' });return (<div><h1>Hello World Example</h1><ul><li>helloNoArgs ({helloNoArgs.status}):{' '}<pre>{JSON.stringify(helloNoArgs.data, null, 2)}</pre></li><li>helloWithArgs ({helloWithArgs.status}):{' '}<pre>{JSON.stringify(helloWithArgs.data, null, 2)}</pre></li></ul></div>);}
使用异步生成器实现流式响应
信息
自 v11 版本起,在使用 httpBatchStreamLink 时支持流式查询。
当查询返回异步生成器时:
-
迭代器结果将以数组形式出现在
data属性中,并随响应到达实时更新 -
收到首个数据块后,
status将立即变为success -
fetchStatus属性将保持fetching状态直至收到最后一个数据块
示例
server/routers/_app.tstsximport { publicProcedure, router } from './trpc';const appRouter = router({iterable: publicProcedure.query(async function* () {for (let i = 0; i < 3; i++) {await new Promise((resolve) => setTimeout(resolve, 500));yield i;}}),});export type AppRouter = typeof appRouter;
server/routers/_app.tstsximport { publicProcedure, router } from './trpc';const appRouter = router({iterable: publicProcedure.query(async function* () {for (let i = 0; i < 3; i++) {await new Promise((resolve) => setTimeout(resolve, 500));yield i;}}),});export type AppRouter = typeof appRouter;
components/MyComponent.tsxtsximport { trpc } from '~/utils';export function MyComponent() {const result = trpc.iterable.useQuery();return (<div>{result.data?.map((chunk, index) => (<Fragment key={index}>{chunk}</Fragment>))}</div>);}
components/MyComponent.tsxtsximport { trpc } from '~/utils';export function MyComponent() {const result = trpc.iterable.useQuery();return (<div>{result.data?.map((chunk, index) => (<Fragment key={index}>{chunk}</Fragment>))}</div>);}
流式传输时的 result 属性:
status | fetchStatus | data |
|---|---|---|
'pending' | 'fetching' | undefined |
'success' | 'fetching' | [] |
'success' | 'fetching' | [1] |
'success' | 'fetching' | [1, 2] |
'success' | 'fetching' | [1, 2, 3] |
'success' | 'idle' | [1, 2, 3] |