You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
  );
}

问题原因分析

  1. 后端异步处理不规范:tRPC的query函数直接返回Todo.list()的Promise,但未显式用async/await处理异步操作。虽然tRPC本身支持返回Promise,但在Serverless环境下可能存在异步调度延迟,导致前端初始无法获取数据。
  2. 前端状态判断不精准:仅通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:50:23