概要
tRPC 公式の Next.js サンプルを読み解いていく。
- Next.js v13
- tRPC v10
Set up with Next.js | tRPC
Recommended file structure
以下のように hello client と表示されるだけのシンプルなアプリ。
tRPCざっくり
公式ドキュメントより全体像。src ディレクトリにまとめられているがどっちでも大丈夫。
.
├── 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
│ │ └── trpc.ts # <-- procedure helpers
│ └── utils
│ └── trpc.ts # <-- your typesafe tRPC hooks
└── [..]
サンプルで追加するファイル。
- src/pages/_app.tsx : withTRPC() HOC を置くところ
- src/pages/api/trpc/[trpc].ts : エンドポイントAPI(実態は routers 配下に実装)
- src/server/routers/_app.ts : エンドポイントの実装
- src/server/routers/posts.ts : 他のエンドポイントも routers 配下にに追加(サンプルでは未実装)
- src/server/context.ts : プロシージャヘルパー(サンプルでは未実装)
- src/server/trpc.ts : server 側 trpc 設定
- src/utils/trpc.ts : client 側の trpc 設定
実装
tRPCエンドポイント作成 (Create a tRPC router)
server 側でエンドポイント API を作成していく。
はじめに initTRPC() を tRPC バックエンドを初期化する。
server/trpc.ts
import { TRPCError, initTRPC } from "@trpc/server";
// Avoid exporting the entire t-object
// since it's not very descriptive.
// For instance, the use of a t variable
// is common in i18n libraries.
const t = initTRPC.create();
// Base router and procedure helpers
export const router = t.router;
export const procedure = t.procedure;
「hello world」を返す API (router) を作成する。
Next.js の API Routes は通常 pages/api
/ 配下に作成していくが、tRPC ルータは server/routers
/ 配下に作成していく。
server/routers/_app.ts
import { z } from 'zod';
import { procedure, router } from '../trpc';
export const appRouter = router({
hello: procedure
.input(
z.object({
text: z.string(),
}),
)
.query(({ input }) => {
return {
greeting: `hello ${input.text}`,
};
}),
});
// export type definition of API
export type AppRouter = typeof appRouter;
Next.js API Routes には tRPC ルータに委任するための設定ファイルを定義しておく。
pages/api/trpc/[trpc].ts
import * as trpcNext from '@trpc/server/adapters/next';
import { appRouter } from '../../../server/routers/_app';
// export API handler
export default trpcNext.createNextApiHandler({
router: appRouter,
createContext: () => ({}),
});
サーバ側はこれで完了。
tRPC クライアント作成 (Create tRPC hooks)
tRPCエンドポイントを呼び出すためのクライアントを設定する。
utils/trpc.ts
import { httpBatchLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
import type { AppRouter } from '../server/routers/_app';
function getBaseUrl() {
if (typeof window !== 'undefined')
// browser should use relative path
return '';
if (process.env.VERCEL_URL)
// reference for vercel.com
return `https://${process.env.VERCEL_URL}`;
if (process.env.RENDER_INTERNAL_HOSTNAME)
// reference for render.com
return `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;
// assume localhost
return `http://localhost:${process.env.PORT ?? 3000}`;
}
export const trpc = createTRPCNext<AppRouter>({
config({ ctx }) {
return {
links: [
httpBatchLink({
/**
* If you want to use SSR, you need to use the server's full URL
* @link https://trpc.io/docs/ssr
**/
url: `${getBaseUrl()}/api/trpc`,
}),
],
/**
* @link https://tanstack.com/query/v4/docs/reference/QueryClient
**/
// queryClientConfig: { defaultOptions: { queries: { staleTime: 60 } } },
};
},
/**
* @link https://trpc.io/docs/ssr
**/
ssr: false,
});
クライアント側はこれで完了。
_app.tsx に HOC 設定 (Configure _app.tsx)
withTRPC() でクライアント側アプリ(MyApp)を包むことで Next.js 全体(クライアント側・サーバ側両方)で trpc を呼び出せるように設定。
pages/_app.tsx
import type { AppType } from 'next/app';
import { trpc } from '../utils/trpc';
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
export default trpc.withTRPC(MyApp);
API を呼び出す (Make an API request)
Next.js のページから作成した tRPC エンドポイントを tRPC クライアント経由で呼び出す。
ここで使っている useQuery
は react-query のもの。
pages/index.tsx
import { trpc } from '../utils/trpc';
export default function IndexPage() {
const hello = trpc.hello.useQuery({ text: 'client' });
if (!hello.data) {
return <div>Loading...</div>;
}
return (
<div>
<p>{hello.data.greeting}</p>
</div>
);
}
参考
Set up with Next.js | tRPC
Recommended file structure
ふんわりざっくり大味で gRPC と tRPC の雰囲気を知る
tRPCを導入したら爆速でWebサービスをリリースできた話
FEELCAT 腹筋ローラー 静音 アブローラー スリムトレーナー アブホイール 上半身筋トレ 膝保護マット付き 耐荷重200kg
FEELCAT 腹筋ローラー 静音 アブローラー スリムトレーナー アブホイール 上半身筋トレ 膝保護マット付き 耐荷重200kg
JEAU CHAU 100% ヒハツパウダー 100g (インド産 ヒハツ) 選別品 ロングペッパー スパイス 香辛料/無添加 無農薬
丁寧に選別した無添加のヒハツパウダーです。 スパイスは香りが命。加工方法も大事ですが、何より鮮度が重要です。 JEAU CHAU(ジョウショー)では、現地から新鮮なスパイスを調達し、素早くパッキング。 自信をもってオススメできる、素晴らしい...
明治 チョコレート効果カカオ95%大袋 180g
●美と健康を考えたチョコレート効果から小袋タイプが新登場! ●まだ食べたことがない人にオススメのトライアルタイプです。 ●明治は、赤ちゃんからお年寄りまで、いろいろなシーンでいつもあなたのそばにありたい。おいしさであなたとずっとつながってい...
Bitly
Bitly
YUBOEST ホットアイマスク USB 充電式 【コードレス】「純シルク製&極上リラックス」軽量 かわいい 持ち運び便利 タイマー設定 温度調節 繰り返し使用可能 家族 ギフトケース包装 (ネイビー)
YUBOEST ホットアイマスク USB 充電式 アイマスク【コードレス】軽量 かわいい シルク 持ち運び便利 タイマー設定 温度調節 繰り返し使用可能 恋人 家族 父の日 恋人 母 誕生日に プレゼント 日語説明書 ギフトケース包装 (ネ...
コメント