使用 Next.js 設定
建議的檔案結構
我們建議使用類似這樣的檔案結構,儘管 tRPC 並未強制執行。這是在 我們的範例 中會看到的內容。本頁面的其餘部分將引導您完成將 tRPC 新增到此結構的流程。
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│ │ └── trpc.ts # <-- procedure helpers│ └── 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│ │ └── trpc.ts # <-- procedure helpers│ └── utils│ └── trpc.ts # <-- your typesafe tRPC hooks└── [..]
將 tRPC 新增到現有的 Next.js 專案
1. 安裝依賴項
- npm
- yarn
- pnpm
- bun
npm install @trpc/server@next @trpc/client@next @trpc/react-query@next @trpc/next@next @tanstack/react-query@latest zod
yarn add @trpc/server@next @trpc/client@next @trpc/react-query@next @trpc/next@next @tanstack/react-query@latest zod
pnpm add @trpc/server@next @trpc/client@next @trpc/react-query@next @trpc/next@next @tanstack/react-query@latest zod
bun add @trpc/server@next @trpc/client@next @trpc/react-query@next @trpc/next@next @tanstack/react-query@latest zod
Next.js 整合實際上是我們的 React Query 整合 和一些 Next.js 特定的整合的組合。
2. 啟用嚴格模式
如果您想使用 Zod 進行輸入驗證,請確定您已在 tsconfig.json
中啟用嚴格模式
tsconfig.jsondiff
"compilerOptions": {+ "strict": true}
tsconfig.jsondiff
"compilerOptions": {+ "strict": true}
如果嚴格模式過於嚴格,你至少會想要啟用 strictNullChecks
tsconfig.jsondiff
"compilerOptions": {+ "strictNullChecks": true}
tsconfig.jsondiff
"compilerOptions": {+ "strictNullChecks": true}
3. 建立一個 tRPC 路由器
在 src/server/trpc.ts
中使用 initTRPC
函式初始化你的 tRPC 後端,並建立你的第一個路由器。我們將在此建立一個簡單的「hello world」路由器和程序 - 但若要更深入地瞭解如何建立你的 tRPC API,你應該參考
- tRPC 資訊的 快速入門指南 和 後端使用文件
- 在你的 Next.js 伺服器中掛載 tRPC 的 Next.js 適配器文件。
查看範例後端
server/trpc.tsts
import { 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 helpersexport const router = t.router;export const procedure = t.procedure;
server/trpc.tsts
import { 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 helpersexport const router = t.router;export const procedure = t.procedure;
server/routers/_app.tsts
import { z } from 'zod';import { procedure, router } from '../trpc';export const appRouter = router({hello: procedure.input(z.object({text: z.string(),}),).query((opts) => {return {greeting: `hello ${opts.input.text}`,};}),});// export type definition of APIexport type AppRouter = typeof appRouter;
server/routers/_app.tsts
import { z } from 'zod';import { procedure, router } from '../trpc';export const appRouter = router({hello: procedure.input(z.object({text: z.string(),}),).query((opts) => {return {greeting: `hello ${opts.input.text}`,};}),});// export type definition of APIexport type AppRouter = typeof appRouter;
pages/api/trpc/[trpc].tsts
import * as trpcNext from '@trpc/server/adapters/next';import { appRouter } from '../../../server/routers/_app';// export API handler// @link https://trpc.dev.org.tw/docs/v11/server/adaptersexport default trpcNext.createNextApiHandler({router: appRouter,createContext: () => ({}),});
pages/api/trpc/[trpc].tsts
import * as trpcNext from '@trpc/server/adapters/next';import { appRouter } from '../../../server/routers/_app';// export API handler// @link https://trpc.dev.org.tw/docs/v11/server/adaptersexport default trpcNext.createNextApiHandler({router: appRouter,createContext: () => ({}),});
4. 建立 tRPC 鉤子
使用 createTRPCNext
函式從你的 API 類型簽章建立一組強類型鉤子。
utils/trpc.tstsx
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 pathreturn '';if (process.env.VERCEL_URL)// reference for vercel.comreturn `https://${process.env.VERCEL_URL}`;if (process.env.RENDER_INTERNAL_HOSTNAME)// reference for render.comreturn `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;// assume localhostreturn `https://#:${process.env.PORT ?? 3000}`;}export const trpc = createTRPCNext<AppRouter>({config(opts) {return {links: [httpBatchLink({/*** If you want to use SSR, you need to use the server's full URL* @link https://trpc.dev.org.tw/docs/v11/ssr**/url: `${getBaseUrl()}/api/trpc`,// You can pass any HTTP headers you wish hereasync headers() {return {// authorization: getAuthCookie(),};},}),],};},/*** @link https://trpc.dev.org.tw/docs/v11/ssr**/ssr: false,});
utils/trpc.tstsx
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 pathreturn '';if (process.env.VERCEL_URL)// reference for vercel.comreturn `https://${process.env.VERCEL_URL}`;if (process.env.RENDER_INTERNAL_HOSTNAME)// reference for render.comreturn `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;// assume localhostreturn `https://#:${process.env.PORT ?? 3000}`;}export const trpc = createTRPCNext<AppRouter>({config(opts) {return {links: [httpBatchLink({/*** If you want to use SSR, you need to use the server's full URL* @link https://trpc.dev.org.tw/docs/v11/ssr**/url: `${getBaseUrl()}/api/trpc`,// You can pass any HTTP headers you wish hereasync headers() {return {// authorization: getAuthCookie(),};},}),],};},/*** @link https://trpc.dev.org.tw/docs/v11/ssr**/ssr: false,});
注意
createTRPCNext
不適用於 tRPC-v9 互通模式。如果你使用互通從 v9 遷移,你應該繼續使用 初始化 tRPC 的舊方法。
5. 設定 _app.tsx
將你的根應用程式頁面包覆在 trpc.withTRPC
HOC 中,類似於這樣
pages/_app.tsxtsx
import type { AppType } from 'next/app';import { trpc } from '../utils/trpc';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
pages/_app.tsxtsx
import type { AppType } from 'next/app';import { trpc } from '../utils/trpc';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
6. 進行 API 請求
你已經設定完成!
現在,您可以使用剛建立的 React hooks 來呼叫您的 API。如需更多詳細資訊,請參閱 React Query 整合
pages/index.tsxtsx
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>);}
pages/index.tsxtsx
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>);}
createTRPCNext()
選項
config
回呼
config
參數是一個函式,用於傳回一個用於設定 tRPC 和 React Query 客戶端的物件。此函式有一個 ctx
輸入,讓您可以存取 Next.js req
物件,以及其他項目。傳回的值可以包含下列屬性
- 必要:
links
用於自訂 tRPC 客戶端和 tRPC 伺服器之間資料流程。 了解更多。- 選用
queryClientConfig
:React QueryQueryClient
的設定物件,由 tRPC React hooks 內部使用:QueryClient 文件queryClient
:React Query QueryClient 執行個體- 注意:您只能提供
queryClient
或queryClientConfig
。
- 注意:您只能提供
transformer
:套用至傳出有效負載的轉換器。進一步了解 資料轉換器abortOnUnmount
:決定在元件解除安裝時是否取消進行中的要求。預設為false
。
overrides
:(預設:undefined
)
ssr
布林值(預設:false
)
伺服器端渲染頁面時,tRPC 是否應等待查詢。預設為 false
。
responseMeta
回呼
伺服器端渲染時設定要求標頭和 HTTP 狀態的能力。
範例
utils/trpc.tstsx
import { createTRPCNext } from '@trpc/next';import type { AppRouter } from '../pages/api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(opts) {/* [...] */},});
utils/trpc.tstsx
import { createTRPCNext } from '@trpc/next';import type { AppRouter } from '../pages/api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(opts) {/* [...] */},});