跳至主内容
版本:11.x

useQuery()

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

useQuery 是数据获取的核心钩子,其工作方式类似于 @tanstack/react-queryuseQuery,但包含一些 trpc 特有的选项和附加功能(如流式传输)。

备注

有关选项和使用模式的详细信息,请参阅 TanStack Query 文档中的查询指南

函数签名

tsx
function useQuery(
input: TInput | SkipToken,
opts?: UseTRPCQueryOptions;
)
interface UseTRPCQueryOptions
extends UseQueryOptions {
trpc: {
ssr?: boolean;
abortOnUnmount?: boolean;
context?: Record<string, unknown>;
}
}
tsx
function useQuery(
input: TInput | SkipToken,
opts?: UseTRPCQueryOptions;
)
interface UseTRPCQueryOptions
extends UseQueryOptions {
trpc: {
ssr?: boolean;
abortOnUnmount?: boolean;
context?: Record<string, unknown>;
}
}

由于 UseTRPCQueryOptions 继承自 @tanstack/react-queryUseQueryOptions,你可以使用其所有选项(如 enabledrefetchOnWindowFocus 等)。此外,我们还提供了一些 trpc 特有选项,允许你在单个过程级别启用或禁用特定行为:

  • trpc.ssr:全局配置中设置了 ssr: true 时,可通过此选项设为 false 来禁用当前查询的 SSR 功能。注意:反向操作无效,即全局配置为 false 时无法为单个过程启用 SSR

  • trpc.abortOnUnmount: 覆盖全局配置,控制组件卸载时是否中止查询

  • trpc.context: 添加可在链接中使用的额外元数据

技巧

如需设置选项但无需传递输入参数,可传入 undefined

你会注意到 input 的自动补全功能完全基于后端定义的 input 结构

用法示例

Backend code
server/routers/_app.ts
tsx
import { 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.ts
tsx
import { 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.tsx
tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
// input is optional, so we don't have to pass second argument
const 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.tsx
tsx
import { trpc } from '../utils/trpc';
export function MyComponent() {
// input is optional, so we don't have to pass second argument
const 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.ts
tsx
import { 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.ts
tsx
import { 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.tsx
tsx
import { 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.tsx
tsx
import { 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 属性:

statusfetchStatusdata
'pending''fetching'undefined
'success''fetching'[]
'success''fetching'[1]
'success''fetching'[1, 2]
'success''fetching'[1, 2, 3]
'success''idle'[1, 2, 3]