Skip to main content
Version: 11.x

useQuery()

useQuery 是数据获取的主要钩子,它的工作方式与 @tanstack/react-queryuseQuery 类似,但具有一些 trpc 特定的选项和流式传输等附加功能。

¥useQuery is the primary hook for data fetching, it works similarly to @tanstack/react-query's useQuery, but with some trpc specific options and additional features like streaming.

注意

有关选项和使用模式的详细信息,请参阅 queries 上的 TanStack Query 文档。

¥For in-depth information about options and usage patterns, refer to the TanStack Query docs on queries.

签名

¥Signature

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 特定选项,可让你在每个程序级别选择加入或退出某些行为:

¥Since UseTRPCQueryOptions extends @tanstack/react-query's UseQueryOptions, you can use any of their options here such as enabled, refetchOnWindowFocus, etc. We also have some trpc specific options that let you opt in or out of certain behaviors on a per-procedure level:

  • trpc.ssr:如果 全局配置 中有 ssr: true,则可以将其设置为 false 以禁用此特定查询的 ssr。请注意,反之则不行,即,如果你的全局配置设置为 false,则无法在过程上启用 ssr。

    ¥trpc.ssr: If you have ssr: true in your global config, you can set this to false to disable ssr for this particular query. Note that this does not work the other way around, i.e., you can not enable ssr on a procedure if your global config is set to false.

  • trpc.abortOnUnmount:覆盖 全局配置 并选择在卸载时中止查询。

    ¥trpc.abortOnUnmount: Override the global config and opt in or out of aborting queries on unmount.

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

    ¥trpc.context: Add extra meta data that could be used in Links.

提示

如果你需要设置任何选项但不想传递任何输入,则可以传递 undefined

¥If you need to set any options but don't want to pass any input, you can pass undefined instead.

你会注意到,你会根据你在后端 input 架构中设置的内容在 input 上获得自动补齐功能。

¥You'll notice that you get autocompletion on the input based on what you have set in your input schema on your backend.

示例用法

¥Example usage

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>
);
}

使用异步生成器进行流式响应

¥Streaming responses using async generators

信息

自 v11 以来,我们现在支持使用 httpBatchStreamLink 时的流式查询。

¥Since v11 we now support streaming queries when using the httpBatchStreamLink.

在查询中返回异步生成器时,你将:

¥When returning an async generators in a query, you will:

  • data 属性中迭代器的结果作为数组获取,该数组会随着响应的到来而更新

    ¥Get the results of the iterator in the data-property as an array which updates as the response comes in

  • 收到第一个块后,status 将立即变为 success

    ¥The status will be success as soon as the first chunk is received.

  • fetchStatus 属性将一直为 fetching,直到收到最后一个块。

    ¥The fetchStatus property which will be fetching until the last chunk is received.

示例

¥Example

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 属性:

¥result properties while streaming:

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