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から直接関数をインポートして使用することもできます。また、これらの関数を使用する際にフィルター上で正しいqueryKeyを取得するために使用できるgetQueryKeyも提供しています。
プロキシクライアント
上記の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;}