#TypeScript #full-stack #trpc
之前是通过配置HttpServer 让服务端运行,现在我们将 TRPC 与 Nextjs 一起使用,并且使用的是 Nextjs 的 AppRouter 模式。
环境版本:
- Nextjs 14
- TRPC
创建项目
首先创建一个 Nextjs 的项目。
npx create-next-app@14
等待项目初始化完毕,切换到新创建的项目目录然后执行运行命令。
cd nextjs-trpc
npm run dev
看到输出 Ready...
说明运行成功,打开浏览器访问 http://localhost:3000
打开页面。
安装 trpc 相关依赖
npm install @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@4 zod
Zod 不是必现的。安装 Zod 是进行输入验证时使用。
启用严格模式。如果使用 Zod 的话应在 tsconfig.json
中启用严格模式(默认为 true)
"compilerOptions": {
"strict": true
}
初始化 trpc 后端路由
新建文件 src/app/server/trpc.ts
。
import { initTRPC } from "@trpc/server";
import { FetchCreateContextFnOptions } from '@trpc/server/adapters/fetch';
// 创建上下文,可以添加一些全局可用的内容:数据库链接、会话等
export const createTRPCContext = async (opts: FetchCreateContextFnOptions) => {
return {
req: opts.req,
};
};
const t = initTRPC.context<typeof createTRPCContext>().create();
export const router = t.router;
export const procedure = t.procedure;
新建 server/routers/_app.ts
,实现并导出一个包含 query 类型 procedure 的 router。
import { z } from 'zod';
import { procedure, router } from '../trpc';
export const appRouter = router({
// 这里实现了一个名为hello的procedure,会将输入的内容拼接为hello XXX,并返回一个对象。
hello: procedure
.input(
z.object({
text: z.string(),
}),
)
.query((opts) => {
return {
greeting: `hello ${opts.input.text}`,
};
}),
});
export type AppRouter = typeof appRouter;
创建 TRPC 客户端
新建 src/app/utils/trpc.ts
import { httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../server/routers/_app';
import { createTRPCReact } from '@trpc/react-query';
export const trpc = createTRPCReact<AppRouter>();
export const client = trpc.createClient({
links:
[httpBatchLink({ url: '/api/trpc' })],
})
新建 src/app/utils/trpc-provider.tsx
// 客户端组件
'use client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { trpc, client } from './trpc';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 5, // 5 s
},
},
});
export default function TRPCProvider({ children }: { children: React.ReactNode }) {
// 提供trpc和ReactQuery上下文
return (
<trpc.Provider client={client} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</trpc.Provider>
);
}
修改 src/app/layout.tsx
import TRPCProvider from "./utils/trpc-provider";
……
<html lang="en">
<body>
// 使用TRPC provider 包裹所有客户端组件
<TRPCProvider>
{children}
</TRPCProvider>
</body>
</html>
使用 TRPC query 接口
新建 src/app/hello/page.tsx
'use client';
import { trpc } from "../utils/trpc"
export default function Hello() {
// 通过trpc调用procedure
const hello = trpc.hello.useQuery({
text: "next.js"
})
// 没有返回时显示Loading
if (!hello.data) {
return <div>Loading...</div>
}
// 显示接口返回的响应数据
return (
<div>
<h1>{hello.data.greeting}</h1>
</div>
)
}
最终效果如: