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