useUtils
이 페이지는 PageTurner AI로 번역되었습니다(베타). 프로젝트 공식 승인을 받지 않았습니다. 오류를 발견하셨나요? 문제 신고 →
useUtils는 @trpc/react-query를 통해 실행한 쿼리의 캐시 데이터를 관리할 수 있게 해주는 헬퍼 함수에 접근할 수 있는 훅입니다. 이러한 헬퍼들은 실제로 @tanstack/react-query의 queryClient 메서드를 간단히 래핑한 것입니다. 여기에서 제공하는 것보다 더 깊이 있는 useUtils 헬퍼의 옵션과 사용 패턴에 대한 정보를 원하신다면, 해당 @tanstack/react-query 문서를 링크하겠으므로 참고하시기 바랍니다.
이 훅은 10.41.0 버전까지 useContext()로 불렸으며, 당분간은 여전히 별칭으로 사용할 수 있습니다.
사용법
useUtils는 라우터에 정의된 모든 사용 가능한 쿼리를 포함한 객체를 반환합니다. trpc 클라이언트 객체와 동일한 방식으로 사용합니다. 특정 쿼리에 도달하면 해당 쿼리 헬퍼를 사용할 수 있습니다. 예를 들어, all 쿼리를 가진 post 라우터가 있다고 가정해 보겠습니다:
server.tstsimport {initTRPC } from '@trpc/server';import {z } from 'zod';constt =initTRPC .create ();constappRouter =t .router ({post :t .router ({all :t .procedure .query (() => {return {posts : [{id : 1,title : 'everlong' },{id : 2,title : 'After Dark' },],};}),}),});export typeAppRouter = typeofappRouter ;
server.tstsimport {initTRPC } from '@trpc/server';import {z } from 'zod';constt =initTRPC .create ();constappRouter =t .router ({post :t .router ({all :t .procedure .query (() => {return {posts : [{id : 1,title : 'everlong' },{id : 2,title : 'After Dark' },],};}),}),});export typeAppRouter = typeofappRouter ;
이제 컴포넌트에서 useUtils가 제공하는 객체를 탐색하여 post.all 쿼리에 도달하면 쿼리 헬퍼를 사용할 수 있습니다!
MyComponent.tsxtsximport {createTRPCReact } from '@trpc/react-query';import type {AppRouter } from './server';consttrpc =createTRPCReact <AppRouter >();functionMyComponent () {constutils =trpc .useUtils ();utils .post .all .f ;}
MyComponent.tsxtsximport {createTRPCReact } from '@trpc/react-query';import type {AppRouter } from './server';consttrpc =createTRPCReact <AppRouter >();functionMyComponent () {constutils =trpc .useUtils ();utils .post .all .f ;}
헬퍼
다음은 useUtils를 통해 접근할 수 있는 헬퍼 목록입니다. 아래 표는 tRPC 헬퍼가 어떤 @tanstack/react-query 헬퍼 메서드를 래핑하는지 보여줍니다. 각 react-query 메서드는 해당 문서/가이드로 연결됩니다:
| tRPC helper wrapper | @tanstack/react-query helper method |
|---|---|
fetch | queryClient.fetchQuery |
prefetch | queryClient.prefetchQuery |
fetchInfinite | queryClient.fetchInfiniteQuery |
prefetchInfinite | queryClient.prefetchInfiniteQuery |
ensureData | queryClient.ensureData |
invalidate | queryClient.invalidateQueries |
refetch | queryClient.refetchQueries |
cancel | queryClient.cancelQueries |
setData | queryClient.setQueryData |
setQueriesData | queryClient.setQueriesData |
getData | queryClient.getQueryData |
setInfiniteData | queryClient.setInfiniteQueryData |
getInfiniteData | queryClient.getInfiniteData |
setMutationDefaults | queryClient.setMutationDefaults |
getMutationDefaults | queryClient.getMutationDefaults |
isMutating | queryClient.isMutating |
reset | queryClient.resetQueries |
❓ 원하는 함수가 여기에 없습니다!
@tanstack/react-query에는 아직 tRPC 컨텍스트에 추가하지 않은 많은 함수가 있습니다. 여기에 없는 함수가 필요하시다면, 기능 요청을 열어 제안해 주세요.
이와 동시에 @tanstack/react-query에서 직접 함수를 임포트하여 사용할 수도 있습니다. 또한 getQueryKey를 제공하므로, 이러한 함수를 사용할 때 필터에 올바른 queryKey를 가져오는 데 활용할 수 있습니다.
프록시 클라이언트
위의 react-query 헬퍼 외에도, 컨텍스트는 tRPC 프록시 클라이언트도 노출합니다. 이를 통해 추가적인 일반 클라이언트를 생성하지 않고도 async/await로 프로시저를 호출할 수 있습니다.
tsximport {useState } from 'react';import {trpc } from './utils/trpc';functionMyComponent () {const [apiKey ,setApiKey ] =useState ('');constutils =trpc .useUtils ();return (<form onSubmit ={async (event ) => {constapiKey = awaitutils .client .apiKey .create .mutate ();setApiKey (apiKey );}}>{/* form content */}</form >);}
tsximport {useState } from 'react';import {trpc } from './utils/trpc';functionMyComponent () {const [apiKey ,setApiKey ] =useState ('');constutils =trpc .useUtils ();return (<form onSubmit ={async (event ) => {constapiKey = awaitutils .client .apiKey .create .mutate ();setApiKey (apiKey );}}>{/* form content */}</form >);}
쿼리 무효화
invalidate 헬퍼를 통해 쿼리를 무효화할 수 있습니다. invalidate는 다른 헬퍼와 달리 라우터 맵의 모든 수준에서 사용할 수 있는 특별한 헬퍼입니다. 즉, 단일 쿼리, 전체 라우터 또는 원한다면 모든 라우터에서 invalidate를 실행할 수 있습니다. 아래 섹션에서 자세히 설명하겠습니다.
단일 쿼리 무효화
단일 프로시저와 관련된 쿼리를 무효화할 수 있으며, 전달된 입력을 기반으로 필터링하여 백엔드에 불필요한 호출을 방지할 수도 있습니다.
예제 코드
tsximport {trpc } from './utils/trpc';functionMyComponent () {constutils =trpc .useUtils ();constmutation =trpc .post .edit .useMutation ({onSuccess (input ) {utils .post .all .invalidate ();utils .post .byId .invalidate ({id :input .id }); // Will not invalidate queries for other id's},});// [...]}
tsximport {trpc } from './utils/trpc';functionMyComponent () {constutils =trpc .useUtils ();constmutation =trpc .post .edit .useMutation ({onSuccess (input ) {utils .post .all .invalidate ();utils .post .byId .invalidate ({id :input .id }); // Will not invalidate queries for other id's},});// [...]}
라우터 전체 무효화
단일 쿼리가 아닌 전체 라우터 범위에서 쿼리를 무효화하는 것도 가능합니다.
예제 코드
Backend code
server/routers/_app.tstsximport {initTRPC } from '@trpc/server';import {z } from 'zod';export constt =initTRPC .create ();export constappRouter =t .router ({// sub Post routerpost :t .router ({all :t .procedure .query (() => {return {posts : [{id : 1,title : 'everlong' },{id : 2,title : 'After Dark' },],};}),byId :t .procedure .input (z .object ({id :z .string (),}),).query (({input }) => {return {post : {id :input ?.id ,title : 'Look me up!' },};}),edit :t .procedure .input (z .object ({id :z .number (),title :z .string () })).mutation (({input }) => {return {post : {id :input .id ,title :input .title } };}),}),// separate user routeruser :t .router ({all :t .procedure .query (() => {return {users : [{name : 'Dave Grohl' }, {name : 'Haruki Murakami' }] };}),}),});
server/routers/_app.tstsximport {initTRPC } from '@trpc/server';import {z } from 'zod';export constt =initTRPC .create ();export constappRouter =t .router ({// sub Post routerpost :t .router ({all :t .procedure .query (() => {return {posts : [{id : 1,title : 'everlong' },{id : 2,title : 'After Dark' },],};}),byId :t .procedure .input (z .object ({id :z .string (),}),).query (({input }) => {return {post : {id :input ?.id ,title : 'Look me up!' },};}),edit :t .procedure .input (z .object ({id :z .number (),title :z .string () })).mutation (({input }) => {return {post : {id :input .id ,title :input .title } };}),}),// separate user routeruser :t .router ({all :t .procedure .query (() => {return {users : [{name : 'Dave Grohl' }, {name : 'Haruki Murakami' }] };}),}),});
tsximport {trpc } from './utils/trpc';functionMyComponent () {constutils =trpc .useUtils ();constinvalidateAllQueriesAcrossAllRouters = () => {// 1️⃣// All queries on all routers will be invalidatedutils .invalidate ();};constinvalidateAllPostQueries = () => {// 2️⃣// All post queries will be invalidatedutils .post .invalidate ();};constinvalidatePostById = () => {// 3️⃣// All queries in the post router with input {id:1} invalidatedutils .post .byId .invalidate ({id : 1 });};// Example queriestrpc .user .all .useQuery (); // Would only be validated by 1️⃣ only.trpc .post .all .useQuery (); // Would be invalidated by 1️⃣ & 2️⃣trpc .post .byId .useQuery ({id : 1 }); // Would be invalidated by 1️⃣, 2️⃣ and 3️⃣trpc .post .byId .useQuery ({id : 2 }); // would be invalidated by 1️⃣ and 2️⃣ but NOT 3️⃣!// [...]}
tsximport {trpc } from './utils/trpc';functionMyComponent () {constutils =trpc .useUtils ();constinvalidateAllQueriesAcrossAllRouters = () => {// 1️⃣// All queries on all routers will be invalidatedutils .invalidate ();};constinvalidateAllPostQueries = () => {// 2️⃣// All post queries will be invalidatedutils .post .invalidate ();};constinvalidatePostById = () => {// 3️⃣// All queries in the post router with input {id:1} invalidatedutils .post .byId .invalidate ({id : 1 });};// Example queriestrpc .user .all .useQuery (); // Would only be validated by 1️⃣ only.trpc .post .all .useQuery (); // Would be invalidated by 1️⃣ & 2️⃣trpc .post .byId .useQuery ({id : 1 }); // Would be invalidated by 1️⃣, 2️⃣ and 3️⃣trpc .post .byId .useQuery ({id : 2 }); // would be invalidated by 1️⃣ and 2️⃣ but NOT 3️⃣!// [...]}
모든 뮤테이션에서 전체 캐시 무효화
뮤테이션이 어떤 쿼리를 무효화해야 하는지 정확히 추적하기 어렵기 때문에, 모든 뮤테이션의 부수 효과로 _전체 캐시_를 무효화하는 것이 실용적인 해결책이 될 수 있습니다. 요청 배칭이 지원되므로, 이 무효화 작업은 현재 보고 있는 페이지의 모든 쿼리를 단일 요청으로 재조회합니다.
이를 돕기 위해 다음 기능을 추가했습니다:
tsimport {createTRPCReact } from '@trpc/react-query';import type {AppRouter } from '../server';export consttrpc =createTRPCReact <AppRouter >({overrides : {useMutation : {/*** This function is called whenever a `.useMutation` succeeds**/asynconSuccess (opts ) {/*** @note that order here matters:* The order here allows route changes in `onSuccess` without* having a flash of content change whilst redirecting.**/// Calls the `onSuccess` defined in the `useQuery()`-options:awaitopts .originalFn ();// Invalidate all queries in the react-query cache:awaitopts .queryClient .invalidateQueries ();},},},});
tsimport {createTRPCReact } from '@trpc/react-query';import type {AppRouter } from '../server';export consttrpc =createTRPCReact <AppRouter >({overrides : {useMutation : {/*** This function is called whenever a `.useMutation` succeeds**/asynconSuccess (opts ) {/*** @note that order here matters:* The order here allows route changes in `onSuccess` without* having a flash of content change whilst redirecting.**/// Calls the `onSuccess` defined in the `useQuery()`-options:awaitopts .originalFn ();// Invalidate all queries in the react-query cache:awaitopts .queryClient .invalidateQueries ();},},},});
추가 옵션
쿼리 헬퍼 외에도, useUtils가 반환하는 객체에는 다음 속성들이 포함됩니다:
tsinterfaceProxyTRPCContextProps <TRouter extendsAnyRouter ,TSSRContext > {/*** The `TRPCClient`*/client :TRPCClient <TRouter >;/*** The SSR context when server-side rendering* @default null*/ssrContext ?:TSSRContext | null;/*** State of SSR hydration.* - `false` if not using SSR.* - `prepass` when doing a prepass to fetch queries' data* - `mounting` before TRPCProvider has been rendered on the client* - `mounted` when the TRPCProvider has been rendered on the client* @default false*/ssrState ?:SSRState ;/*** Abort loading query calls when unmounting a component - usually when navigating to a new page* @default false*/abortOnUnmount ?: boolean;}
tsinterfaceProxyTRPCContextProps <TRouter extendsAnyRouter ,TSSRContext > {/*** The `TRPCClient`*/client :TRPCClient <TRouter >;/*** The SSR context when server-side rendering* @default null*/ssrContext ?:TSSRContext | null;/*** State of SSR hydration.* - `false` if not using SSR.* - `prepass` when doing a prepass to fetch queries' data* - `mounting` before TRPCProvider has been rendered on the client* - `mounted` when the TRPCProvider has been rendered on the client* @default false*/ssrState ?:SSRState ;/*** Abort loading query calls when unmounting a component - usually when navigating to a new page* @default false*/abortOnUnmount ?: boolean;}