メインコンテンツへスキップ
バージョン: 11.x

リンクの概要

リンクを使用すると、tRPCクライアントとサーバー間のデータの流れをカスタマイズできます。リンクは、tRPC操作(クエリ、ミューテーション、またはサブスクリプション)に対する自己完結型の変更、または操作に基づく副作用(ロギングなど)のいずれか1つだけを行う必要があります。

リンクをまとめて配列に構成し、linksプロパティを介してtRPCクライアント構成に提供できます。これはリンクチェーンを表します。つまり、tRPCクライアントはリクエストの実行時にlinks配列に追加された順にリンクを実行し、応答の処理時に逆順に再度実行します。以下は、リンクチェーンの視覚的な表現です。

tRPCリンク図tRPCリンク図。 Apolloに基づいています。

以下の例はNext.jsを使用していることを前提としていますが、下記と同じものがvanilla tRPCクライアントを使用している場合に追加できます。

utils/trpc.ts
tsx
import { httpBatchLink, loggerLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
export default createTRPCNext<AppRouter>({
config() {
const url = `http://localhost:3000`;
return {
links: [
loggerLink(),
httpBatchLink({
url,
}),
],
};
},
});
utils/trpc.ts
tsx
import { httpBatchLink, loggerLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
export default createTRPCNext<AppRouter>({
config() {
const url = `http://localhost:3000`;
return {
links: [
loggerLink(),
httpBatchLink({
url,
}),
],
};
},
});

リンクは、TRPCLinkタイプに従う関数です。各リンクは3つの部分で構成されています。

  1. リンクは、TRPCClientRuntime型のパラメータを持つ関数を返します。この引数はtRPCによって渡され、終端リンクを作成するときに使用されます。終端リンクを作成しない場合は、パラメータなしの関数を作成できます。この場合、リンクは呼び出さずにlinks配列に追加する必要があります(links: [..., myLink, httpBatchLink(...)])。
  2. ステップ1の関数は、2つのプロパティを持つオブジェクトを受け取る別の関数を返します。1つはクライアントによって実行されているOperationであるop、もう1つはチェーンの次のリンクを呼び出すために使用する関数であるnextです。
  3. ステップ2の関数は、@trpc/serverによって提供されるobservable関数を返す最終的な関数を返します。observableは、リンクがチェーンの次のリンクに操作結果の処理方法を通知するのに役立つobserverを受け取る関数を受け入れます。この関数では、next(op)を返すか、nextをサブスクライブして、リンクが操作結果を処理できるようにすることができます。

utils/customLink.ts
tsx
import { TRPCLink } from '@trpc/client';
import { observable } from '@trpc/server/observable';
import type { AppRouter } from 'server/routers/_app';
export const customLink: TRPCLink<AppRouter> = () => {
// here we just got initialized in the app - this happens once per app
// useful for storing cache for instance
return ({ next, op }) => {
// this is when passing the result to the next link
// each link needs to return an observable which propagates results
return observable((observer) => {
console.log('performing operation:', op);
const unsubscribe = next(op).subscribe({
next(value) {
console.log('we received value', value);
observer.next(value);
},
error(err) {
console.log('we received error', err);
observer.error(err);
},
complete() {
observer.complete();
},
});
return unsubscribe;
});
};
};
utils/customLink.ts
tsx
import { TRPCLink } from '@trpc/client';
import { observable } from '@trpc/server/observable';
import type { AppRouter } from 'server/routers/_app';
export const customLink: TRPCLink<AppRouter> = () => {
// here we just got initialized in the app - this happens once per app
// useful for storing cache for instance
return ({ next, op }) => {
// this is when passing the result to the next link
// each link needs to return an observable which propagates results
return observable((observer) => {
console.log('performing operation:', op);
const unsubscribe = next(op).subscribe({
next(value) {
console.log('we received value', value);
observer.next(value);
},
error(err) {
console.log('we received error', err);
observer.error(err);
},
complete() {
observer.complete();
},
});
return unsubscribe;
});
};
};

参考文献

カスタムリンクの作成に関してより現実的な参照が必要な場合は、GitHubでtRPCが提供する組み込みリンクのいくつかを確認できます。

終端リンクは、リンクチェーンの最後のリンクです。next関数を呼び出す代わりに、終端リンクは構成されたtRPC操作をtRPCサーバーに送信し、OperationResultEnvelopeを返す役割を担います。

tRPCクライアント構成に追加するlinks配列には、少なくとも1つのリンクが含まれている必要があり、そのリンクは終端リンクである必要があります。linksの最後に終端リンクがない場合、tRPC操作はtRPCサーバーに送信されません。

httpBatchLinkは、tRPCで推奨される終端リンクです。

httpLinkおよびwsLinkは、終端リンクの他の例です。

コンテキストの管理

操作がリンクチェーンに沿って移動すると、各リンクが読み取りおよび変更できるコンテキストが維持されます。これにより、リンクは他のリンクが実行ロジックで使用するメタデータをチェーンに沿って渡すことができます。

op.contextにアクセスして、現在のコンテキストオブジェクトを取得し、変更します。

queryまたはuseQueryフック(またはmutationsubscriptionなど)にコンテキストパラメータを提供することで、特定の操作のコンテキストオブジェクトの初期値を設定できます。

使用例については、特定の要求のバッチ処理を無効にするを参照してください。