/ default / 2浏览

TRPC快速入门(7)

#TypeScript #full-stack #trpc
之前是通过配置HttpServer 让服务端运行,现在我们将 TRPC 与 Nextjs 一起使用,并且使用的是 Nextjs 的 AppRouter 模式。
环境版本:

  • Nextjs 14
  • TRPC

创建项目

首先创建一个 Nextjs 的项目。
npx create-next-app@14
新建Nextjs项目
等待项目初始化完毕,切换到新创建的项目目录然后执行运行命令。

cd nextjs-trpc
npm run dev

运行Nextjs项目
看到输出 Ready... 说明运行成功,打开浏览器访问 http://localhost:3000 打开页面。
Nextjs页面

安装 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>
    )
}

最终效果如:
TRPC请求未响应
TRPC返回响应

A阿尔不二