TRPC v10如何实现含短横线的路由路径?
TRPC v10 中短横线分隔路由的简洁实现方式
v9 与 v10 的路由定义差异
在 TRPC v9 中,路由采用链式调用定义:
const appRouter = trpc.router() .query('greeting', { input: z.string(), resolve({ input }) { return `hello ${input}!`; }, });
到了 TRPC v10,路由改为对象字面量形式:
const appRouter = router({ greeting: publicProcedure .input(z.string()) .query(({ input }) => `hello ${input}!`), });
问题:短横线分隔路由的调用繁琐
如果要实现 register-user 这类短横线分隔的路由,常规写法在前后端都不够简洁:
服务端代码
// server-side const userRouter = router({ ["register-user"]: procedure .input(registerUserInputSchema) .mutation(async ({ ctx, input }) => { // 业务逻辑实现 }), });
前端调用代码
// fe-side function RegisterPage() { const { handleSubmit, register } = useForm(); // 因路由合并带有 users 前缀(详见附录) const {} = trpc["users"]["register-user"].useMutation(); return ( <> <form action=""></form> <Link href="/login">Login</Link> </> ); }
这种写法必须用方括号访问属性,不够直观,下面提供两种更简洁的实现思路:
解决方案1:用 alias 指定路径别名
TRPC v10 支持通过 alias 方法为路由设置自定义路径,服务端用驼峰式命名保持代码整洁,同时对外暴露短横线分隔的路径:
// server-side const userRouter = router({ registerUser: procedure .input(registerUserInputSchema) .mutation(async ({ ctx, input }) => { // 业务逻辑实现 }) .alias("register-user"), // 对外暴露短横线分隔的路径 });
前端调用时直接用驼峰式点语法即可:
// fe-side function RegisterPage() { const { handleSubmit, register } = useForm(); const {} = trpc.users.registerUser.useMutation(); return ( <> <form action=""></form> <Link href="/login">Login</Link> </> ); }
解决方案2:中间件自动转换路径格式
如果不想逐个设置别名,可以编写中间件,自动将驼峰式路由名转为短横线分隔的路径:
// 自定义路径转换中间件 const kebabCaseMiddleware = t.middleware(async ({ ctx, next, path }) => { // 驼峰转短横线格式 const kebabPath = path.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase(); return next({ ctx, path: kebabPath, }); }); // 将中间件应用到全局 procedure const publicProcedure = t.procedure.use(kebabCaseMiddleware); // 服务端用驼峰式定义路由 const userRouter = router({ registerUser: publicProcedure .input(registerUserInputSchema) .mutation(async ({ ctx, input }) => { // 业务逻辑实现 }), });
这种方式下,前端依然用简洁的点语法调用,外部访问的路径会自动转为 register-user 格式。
附录:users. 前缀的由来
调用路由时的 users. 前缀,是因为根路由中合并了用户子路由:
import { router } from "../trpc"; import { userRouter } from "./user.router"; export const appRouter = router({ users: userRouter, // 合并用户路由,因此前端调用需加 users 前缀 }); export type AppRouter = typeof appRouter;
内容的提问来源于stack exchange,提问作者netlemon
相关产品推荐
相关产品推荐

