React TS调用tRPC接口先返回undefined后获取数据的问题排查
问题:Serverless + tRPC 接口初始返回 undefined,后续才返回正确数据
问题背景
使用Serverless框架结合tRPC实现路由时,前端调用后端接口会出现首次返回undefined,之后才能获取到正确数据的情况,尝试添加await但未解决问题。
相关代码片段
路由定义代码
const t = initTRPC.create(); const appRouter = t.router({ Todos: t.procedure .query(() => { // console.log(Todo.list()) return Todo.list() }) })
数据库查询代码
export function list() { return PG.DB.selectFrom("todo") .selectAll() .orderBy("todoID") .execute() }
前端组件代码
function IndexPage() { const todoList = trpc.Todos.useQuery()?.data; console.log("--------", todoList) if (!todoList) return <div>Loading...</div>; return ( <div> <table className="table table-bordered"> <thead> <tr> <th className="th-sm">task</th> </tr> </thead> <tbody> {todoList.map((todo) => { return ( <> <tr key={todo?.todoID}> <td>{todo.task}</td> </tr> </> ); })} </tbody> </table> </div> ); }
问题原因分析
- 后端异步处理不规范:tRPC的
query函数直接返回Todo.list()的Promise,但未显式用async/await处理异步操作。虽然tRPC本身支持返回Promise,但在Serverless环境下可能存在异步调度延迟,导致前端初始无法获取数据。 - 前端状态判断不精准:仅通过
todoList是否存在判断加载状态,没有利用tRPC(基于React Query)提供的isLoading等官方状态字段,对初始加载阶段的判断逻辑不够严谨。
修复方案
1. 规范后端异步逻辑
修改tRPC路由的query函数,添加async关键字并await数据库查询结果,确保异步操作被正确处理:
const appRouter = t.router({ Todos: t.procedure .query(async () => { return await Todo.list(); }) })
2. 优化前端状态管理
使用useQuery返回的isLoading、isError状态字段精准控制组件渲染,替代单纯判断data是否存在:
function IndexPage() { const { data: todoList, isLoading, isError } = trpc.Todos.useQuery(); if (isLoading) return <div>Loading...</div>; if (isError) return <div>加载失败,请稍后重试</div>; console.log("--------", todoList); return ( <div> <table className="table table-bordered"> <thead> <tr> <th className="th-sm">task</th> </tr> </thead> <tbody> {todoList.map((todo) => ( <tr key={todo.todoID}> <td>{todo.task}</td> </tr> ))} </tbody> </table> </div> ); }
额外检查点
确认数据库操作的execute()方法确实返回Promise,保证Todo.list()是合法的异步函数。
内容的提问来源于stack exchange,提问作者BillyG
相关产品推荐
相关产品推荐

