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

サーバーサイドヘルパー

非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

サーバーサイドヘルパーは、サーバー上でクエリをプリフェッチするための一連のヘルパー関数を提供します。これはSSGに有用ですが、ssr: trueを使用しない場合のSSRでも役立ちます。

サーバーサイドヘルパーによるプリフェッチでは、クエリキャッシュをサーバー上で事前に埋めることができ、これらのクエリがクライアント側で初期フェッチを必要としないことを意味します。

サーバーサイドヘルパーの2つの使用方法

1. 内部ルーター

この方法は、tRPCルーターに直接アクセスできる場合に使用します。例:モノリシックなNext.jsアプリケーションを開発する場合。

ヘルパーを使用すると、tRPCはサーバーサイドコールと同様に、HTTPリクエストなしでサーバー上で直接プロシージャを呼び出します。 つまり、通常のようにリクエスト(req)やレスポンス(res)を手元で扱えません。コンテキスト作成時に通常埋められるreqresを含まないコンテキストでサーバーサイドヘルパーを初期化してください。このシナリオでは"内部"と"外部"コンテキストの概念をお勧めします。

ts
import { createServerSideHelpers } from '@trpc/react-query/server';
import { createContext } from '~/server/context';
import superjson from 'superjson';
const helpers = createServerSideHelpers({
router: appRouter,
ctx: await createContext(),
transformer: superjson, // optional - adds superjson serialization
});
ts
import { createServerSideHelpers } from '@trpc/react-query/server';
import { createContext } from '~/server/context';
import superjson from 'superjson';
const helpers = createServerSideHelpers({
router: appRouter,
ctx: await createContext(),
transformer: superjson, // optional - adds superjson serialization
});

2. 外部ルーター

この方法は、tRPCルーターに直接アクセスできない場合に使用します。例:Next.jsアプリケーションと独立してホストされるAPIを開発する場合。

ts
import { createTRPCProxyClient } from '@trpc/client';
import { createServerSideHelpers } from '@trpc/react-query/server';
import superjson from 'superjson';
const proxyClient = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000/api/trpc',
}),
],
transformer: superjson,
});
const helpers = createServerSideHelpers({
client: proxyClient,
});
ts
import { createTRPCProxyClient } from '@trpc/client';
import { createServerSideHelpers } from '@trpc/react-query/server';
import superjson from 'superjson';
const proxyClient = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000/api/trpc',
}),
],
transformer: superjson,
});
const helpers = createServerSideHelpers({
client: proxyClient,
});

ヘルパーの使用方法

サーバーサイドヘルパーメソッドは、すべてのルーターをキーとして持つtRPCクライアントに似たオブジェクトを返します。ただし、useQueryuseMutationの代わりに、prefetchfetchprefetchInfinitefetchInfinite関数が提供されます。

prefetchfetchの主な違いは、fetchが通常の関数呼び出しのように動作してクエリ結果を返すのに対し、prefetchは結果を返さず例外もスローしない点です。そのような動作が必要な場合は代わりにfetchを使用してください。prefetchはクエリをキャッシュに追加し、これをデハイドレートしてクライアントに送信します。

ts
return {
props: {
// very important - use `trpcState` as the key
trpcState: helpers.dehydrate(),
},
};
ts
return {
props: {
// very important - use `trpcState` as the key
trpcState: helpers.dehydrate(),
},
};

経験則として、クライアント側で必要とわかっているクエリにはprefetchを、サーバー側で結果を使用したいクエリにはfetchを使用します。

これらの関数はすべてreact-queryの機能をラップしたものです。詳細についてはreact-queryのドキュメントをご覧ください。

情報

完全なサンプルはE2E SSGテスト例をご覧ください。

Next.jsの使用例

pages/posts/[id].tsx
tsx
import { createServerSideHelpers } from '@trpc/react-query/server';
import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';
import { appRouter } from 'server/routers/_app';
import superjson from 'superjson';
import { trpc } from 'utils/trpc';
export async function getServerSideProps(
context: GetServerSidePropsContext<{ id: string }>,
) {
const helpers = createServerSideHelpers({
router: appRouter,
ctx: {},
transformer: superjson,
});
const id = context.params?.id as string;
/*
* Prefetching the `post.byId` query.
* `prefetch` does not return the result and never throws - if you need that behavior, use `fetch` instead.
*/
await helpers.post.byId.prefetch({ id });
// Make sure to return { props: { trpcState: helpers.dehydrate() } }
return {
props: {
trpcState: helpers.dehydrate(),
id,
},
};
}
export default function PostViewPage(
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) {
const { id } = props;
const postQuery = trpc.post.byId.useQuery({ id });
if (postQuery.status !== 'success') {
// won't happen since the query has been prefetched
return <>Loading...</>;
}
const { data } = postQuery;
return (
<>
<h1>{data.title}</h1>
<em>Created {data.createdAt.toLocaleDateString()}</em>
<p>{data.text}</p>
<h2>Raw data:</h2>
<pre>{JSON.stringify(data, null, 4)}</pre>
</>
);
}
pages/posts/[id].tsx
tsx
import { createServerSideHelpers } from '@trpc/react-query/server';
import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';
import { appRouter } from 'server/routers/_app';
import superjson from 'superjson';
import { trpc } from 'utils/trpc';
export async function getServerSideProps(
context: GetServerSidePropsContext<{ id: string }>,
) {
const helpers = createServerSideHelpers({
router: appRouter,
ctx: {},
transformer: superjson,
});
const id = context.params?.id as string;
/*
* Prefetching the `post.byId` query.
* `prefetch` does not return the result and never throws - if you need that behavior, use `fetch` instead.
*/
await helpers.post.byId.prefetch({ id });
// Make sure to return { props: { trpcState: helpers.dehydrate() } }
return {
props: {
trpcState: helpers.dehydrate(),
id,
},
};
}
export default function PostViewPage(
props: InferGetServerSidePropsType<typeof getServerSideProps>,
) {
const { id } = props;
const postQuery = trpc.post.byId.useQuery({ id });
if (postQuery.status !== 'success') {
// won't happen since the query has been prefetched
return <>Loading...</>;
}
const { data } = postQuery;
return (
<>
<h1>{data.title}</h1>
<em>Created {data.createdAt.toLocaleDateString()}</em>
<p>{data.text}</p>
<h2>Raw data:</h2>
<pre>{JSON.stringify(data, null, 4)}</pre>
</>
);
}