サーバーサイドヘルパー
このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
サーバーサイドヘルパーは、サーバー上でクエリをプリフェッチするための一連のヘルパー関数を提供します。これはSSGに有用ですが、ssr: trueを使用しない場合のSSRでも役立ちます。
サーバーサイドヘルパーによるプリフェッチでは、クエリキャッシュをサーバー上で事前に埋めることができ、これらのクエリがクライアント側で初期フェッチを必要としないことを意味します。
サーバーサイドヘルパーの2つの使用方法
1. 内部ルーター
この方法は、tRPCルーターに直接アクセスできる場合に使用します。例:モノリシックなNext.jsアプリケーションを開発する場合。
ヘルパーを使用すると、tRPCはサーバーサイドコールと同様に、HTTPリクエストなしでサーバー上で直接プロシージャを呼び出します。
つまり、通常のようにリクエスト(req)やレスポンス(res)を手元で扱えません。コンテキスト作成時に通常埋められるreqやresを含まないコンテキストでサーバーサイドヘルパーを初期化してください。このシナリオでは"内部"と"外部"コンテキストの概念をお勧めします。
tsimport { 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});
tsimport { 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を開発する場合。
tsimport { createTRPCClient } from '@trpc/client';import { createServerSideHelpers } from '@trpc/react-query/server';import superjson from 'superjson';const proxyClient = createTRPCClient<AppRouter>({links: [httpBatchLink({url: 'http://localhost:3000/api/trpc',}),],});const helpers = createServerSideHelpers({client: proxyClient,});
tsimport { createTRPCClient } from '@trpc/client';import { createServerSideHelpers } from '@trpc/react-query/server';import superjson from 'superjson';const proxyClient = createTRPCClient<AppRouter>({links: [httpBatchLink({url: 'http://localhost:3000/api/trpc',}),],});const helpers = createServerSideHelpers({client: proxyClient,});
ヘルパーの使用方法
サーバーサイドヘルパーメソッドは、すべてのルーターをキーとして持つtRPCクライアントに似たオブジェクトを返します。ただし、useQueryやuseMutationの代わりに、prefetch、fetch、prefetchInfinite、fetchInfinite関数が提供されます。
prefetchとfetchの主な違いは、fetchが通常の関数呼び出しのように動作してクエリ結果を返すのに対し、prefetchは結果を返さず例外もスローしない点です。そのような動作が必要な場合は代わりにfetchを使用してください。prefetchはクエリをキャッシュに追加し、これをデハイドレートしてクライアントに送信します。
tsreturn {props: {// very important - use `trpcState` as the keytrpcState: helpers.dehydrate(),},};
tsreturn {props: {// very important - use `trpcState` as the keytrpcState: helpers.dehydrate(),},};
経験則として、クライアント側で必要とわかっているクエリにはprefetchを、サーバー側で結果を使用したいクエリにはfetchを使用します。
これらの関数はすべてreact-query関数のラッパーです。詳細については公式ドキュメントを参照してください。
完全なサンプルはE2E SSGテスト例をご覧ください。
Next.jsの使用例
pages/posts/[id].tsxtsximport { createServerSideHelpers } from '@trpc/react-query/server';import { appRouter } from '~/server/routers/_app';import { trpc } from '~/utils/trpc';import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';import superjson from 'superjson';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 prefetchedreturn <>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].tsxtsximport { createServerSideHelpers } from '@trpc/react-query/server';import { appRouter } from '~/server/routers/_app';import { trpc } from '~/utils/trpc';import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';import superjson from 'superjson';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 prefetchedreturn <>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></>);}