본문 바로가기
버전: 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를 확장하므로 enabled, refetchOnWindowFocus 같은 옵션을 모두 사용할 수 있습니다. 또한 프로시저 단위로 특정 동작을 선택/해제할 수 있는 trpc 전용 옵션이 존재합니다:

  • trpc.ssr: 전역 설정에서 ssr: true인 경우, 특정 쿼리에 대해 SSR을 비활성화하려면 false로 설정하세요. 전역 설정이 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>
);
}

async generator를 사용한 스트리밍 응답

정보

v11부터 httpBatchStreamLink 사용 시 스트리밍 쿼리를 지원합니다.

쿼리에서 async generator를 반환할 경우:

  • 응답 수신 시 업데이트되는 반복자(iterator) 결과를 배열 형태data 속성에서 확인 가능

  • 첫 청크 수신 시 statussuccess로 변경됨

  • 마지막 청크 수신 전까지 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]