Next.jsでの使用方法
このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
新規プロジェクトでtRPCを使用する場合は、スタータープロジェクトとして、または参考資料として以下のサンプルプロジェクトの利用を検討してください: tRPCサンプルプロジェクト
tRPCとNext.jsは最高の組み合わせです!Next.jsを使えばクライアントとサーバーを単一のコードベースで簡単に構築でき、両者の間で型を共有することが容易になります。
tRPCにはNext.js開発者体験を可能な限りシームレスにする専用ツールが組み込まれています。
推奨ファイル構造
推奨されるファイル構造(強制ではありません)。これはサンプルプロジェクトから始めた場合の構成です。
graphql.├── prisma # <-- if prisma is added│ └── [..]├── src│ ├── pages│ │ ├── _app.tsx # <-- add `withTRPC()`-HOC here│ │ ├── api│ │ │ └── trpc│ │ │ └── [trpc].ts # <-- tRPC HTTP handler│ │ └── [..]│ ├── server│ │ ├── routers│ │ │ ├── app.ts # <-- main app router│ │ │ ├── post.ts # <-- sub routers│ │ │ └── [..]│ │ ├── context.ts # <-- create app context│ │ └── createRouter.ts # <-- router helper│ └── utils│ └── trpc.ts # <-- your typesafe tRPC hooks└── [..]
graphql.├── prisma # <-- if prisma is added│ └── [..]├── src│ ├── pages│ │ ├── _app.tsx # <-- add `withTRPC()`-HOC here│ │ ├── api│ │ │ └── trpc│ │ │ └── [trpc].ts # <-- tRPC HTTP handler│ │ └── [..]│ ├── server│ │ ├── routers│ │ │ ├── app.ts # <-- main app router│ │ │ ├── post.ts # <-- sub routers│ │ │ └── [..]│ │ ├── context.ts # <-- create app context│ │ └── createRouter.ts # <-- router helper│ └── utils│ └── trpc.ts # <-- your typesafe tRPC hooks└── [..]
既存のNext.jsプロジェクトにtRPCを追加
1. 依存関係のインストール
bashyarn add @trpc/client @trpc/server @trpc/react @trpc/next zod react-query@3
bashyarn add @trpc/client @trpc/server @trpc/react @trpc/next zod react-query@3
-
React Query:
@trpc/reactは@tanstack/react-queryの薄いラッパーを提供します。peer dependencyとして必須です。 -
Zod: ほとんどの例では入力検証にZodを使用しており、必須ではありませんが強く推奨します。お好みの検証ライブラリ(Yup、Superstruct、io-tsなど)も使用可能です。実際、
parse、create、validateSyncメソッドを含むオブジェクトであれば動作します
2. 厳格モードを有効化
Zodを使用した入力検証を行う場合は、tsconfig.jsonで厳格モード(strict mode)を有効化してください:
json// tsconfig.json{// ..."compilerOptions": {// ..."strict": true}}
json// tsconfig.json{// ..."compilerOptions": {// ..."strict": true}}
厳格モード(strict mode)が厳しすぎる場合は、少なくともstrictNullChecksを有効にしてください:
json// tsconfig.json{// ..."compilerOptions": {// ..."strictNullChecks": true}}
json// tsconfig.json{// ..."compilerOptions": {// ..."strictNullChecks": true}}
3. tRPCルーターを作成
tRPCルーターは./pages/api/trpc/[trpc].tsに実装します。ルーターを複数のサブルーターに分割する必要がある場合は、プロジェクトルート直下のserverディレクトリに実装し、./pages/api/trpc/[trpc].tsにインポートしてマージし、単一のルートappRouterとして統合します。
View sample router
./pages/api/trpc/[trpc].tstsimport * as trpc from '@trpc/server';import * as trpcNext from '@trpc/server/adapters/next';import { z } from 'zod';export const appRouter = trpc.router().query('hello', {input: z.object({text: z.string().nullish(),}).nullish(),resolve({ input }) {return {greeting: `hello ${input?.text ?? 'world'}`,};},});// export type definition of APIexport type AppRouter = typeof appRouter;// export API handlerexport default trpcNext.createNextApiHandler({router: appRouter,createContext: () => null,});
./pages/api/trpc/[trpc].tstsimport * as trpc from '@trpc/server';import * as trpcNext from '@trpc/server/adapters/next';import { z } from 'zod';export const appRouter = trpc.router().query('hello', {input: z.object({text: z.string().nullish(),}).nullish(),resolve({ input }) {return {greeting: `hello ${input?.text ?? 'world'}`,};},});// export type definition of APIexport type AppRouter = typeof appRouter;// export API handlerexport default trpcNext.createNextApiHandler({router: appRouter,createContext: () => null,});
4. tRPCフックを作成
APIの型シグネチャを使用して、厳密に型付けされたフック一式を作成します。
utils/trpc.tstsximport { createReactQueryHooks } from '@trpc/react';import type { AppRouter } from '../pages/api/trpc/[trpc]';export const trpc = createReactQueryHooks<AppRouter>();// => { useQuery: ..., useMutation: ...}
utils/trpc.tstsximport { createReactQueryHooks } from '@trpc/react';import type { AppRouter } from '../pages/api/trpc/[trpc]';export const trpc = createReactQueryHooks<AppRouter>();// => { useQuery: ..., useMutation: ...}
5. _app.tsxを設定
createReactQueryHooks関数はContext APIを介して特定のパラメータが渡されることを想定しています。これらのパラメータを設定するには、withTRPC高階コンポーネントを使用してカスタムの_app.tsxを作成します:
pages/_app.tsxtsximport { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';import type { AppRouter } from './api/trpc/[trpc]';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config(config) {/*** If you want to use SSR, you need to use the server's full URL* @see https://trpc.io/docs/ssr*/const url = process.env.VERCEL_URL? `https://${process.env.VERCEL_URL}/api/trpc`: 'http://localhost:3000/api/trpc';return {url,/*** @see https://tanstack.com/query/v3/docs/react/reference/QueryClient*/// queryClientConfig: { defaultOptions: { queries: { staleTime: 60 } } },};},/*** @see https://trpc.io/docs/ssr*/ssr: true,})(MyApp);
pages/_app.tsxtsximport { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';import type { AppRouter } from './api/trpc/[trpc]';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config(config) {/*** If you want to use SSR, you need to use the server's full URL* @see https://trpc.io/docs/ssr*/const url = process.env.VERCEL_URL? `https://${process.env.VERCEL_URL}/api/trpc`: 'http://localhost:3000/api/trpc';return {url,/*** @see https://tanstack.com/query/v3/docs/react/reference/QueryClient*/// queryClientConfig: { defaultOptions: { queries: { staleTime: 60 } } },};},/*** @see https://trpc.io/docs/ssr*/ssr: true,})(MyApp);
6. APIリクエストの実行
pages/index.tsxtsximport { trpc } from '../utils/trpc';export default function IndexPage() {const hello = trpc.useQuery(['hello', { text: 'client' }]);if (!hello.data) {return <div>Loading...</div>;}return (<div><p>{hello.data.greeting}</p></div>);}
pages/index.tsxtsximport { trpc } from '../utils/trpc';export default function IndexPage() {const hello = trpc.useQuery(['hello', { text: 'client' }]);if (!hello.data) {return <div>Loading...</div>;}return (<div><p>{hello.data.greeting}</p></div>);}
withTRPC()のオプション
configコールバック
config引数はtRPCおよびReact Queryクライアントを設定するオブジェクトを返す関数です。この関数はNext.jsのreqオブジェクトなどにアクセスできるctx入力を受け取り、以下のプロパティを含むオブジェクトを返します:
-
以下のいずれか一つが必須です:
url: APIのURLlinks: tRPCクライアントとtRPCサーバー間のデータフローをカスタマイズするリンク。詳細
-
オプション:
queryClientConfig: tRPC Reactフック内部で使用されるReact QueryのQueryClient設定オブジェクト。QueryClientドキュメントheaders: 送信tRPCリクエストのヘッダーオブジェクト、またはヘッダーオブジェクトを返す関数transformer: 送信ペイロードに適用するトランスフォーマー。データトランスフォーマーを参照fetch: tRPC内部で使用されるfetchの実装をカスタマイズAbortController: tRPC内部で使用されるAbortControllerの実装をカスタマイズ
ssr-boolean (デフォルト: false)
サーバーサイドレンダリング時にtRPCがクエリを待機するかどうか。デフォルトはfalseです。
responseMeta-コールバック
サーバーサイドレンダリング時のリクエストヘッダーとHTTPステータスの設定
使用例
pages/_app.tsxtsxexport default withTRPC<AppRouter>({config(config) {/* [...] */},ssr: true,responseMeta({ clientErrors, ctx }) {if (clientErrors.length) {// propagate first http error from API callsreturn {status: clientErrors[0].data?.httpStatus ?? 500,};}// cache full page for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {'Cache-Control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,};},})(MyApp);
pages/_app.tsxtsxexport default withTRPC<AppRouter>({config(config) {/* [...] */},ssr: true,responseMeta({ clientErrors, ctx }) {if (clientErrors.length) {// propagate first http error from API callsreturn {status: clientErrors[0].data?.httpStatus ?? 500,};}// cache full page for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {'Cache-Control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,};},})(MyApp);
次のステップ
コンポーネント内でのクエリおよびミューテーション実行に関する追加情報は、@trpc/reactドキュメントを参照してください。