Next 13 使用tRPC客户端Promise触发报错求助
解决Next.js 13服务端组件调用tRPC时的"[object Promise]"错误
错误原因分析
你遇到的Objects are not valid as a React child (found: [object Promise])错误,核心是React无法将Promise作为子元素渲染,常见触发场景有两种:
- 把标记为async的服务端组件,直接放在了
'use client'标记的客户端组件中使用——客户端组件不支持async函数组件,async组件会返回Promise,被React误当作子元素。 - tRPC客户端在服务端组件中的初始化方式错误,导致数据请求未正确解析(虽然你用了await,但如果客户端实例是为浏览器环境创建的,可能在服务端运行时出现异常)。
解决方案
1. 确保组件的服务端身份正确
- 确认
PortfolioSection组件所在文件没有添加'use client'指令(Next.js 13 app目录下的组件默认是服务端组件)。 - 只在服务端组件、app目录的页面/布局中渲染
PortfolioSection,不要在客户端组件中直接引入它。如果需要在客户端组件中使用,要通过props传入数据,而非直接渲染async服务端组件。
2. 使用tRPC服务端调用器(推荐)
在服务端组件中,应该直接使用tRPC的server-side caller,而非客户端实例,避免环境不兼容问题:
// 替换你的fetchProjects和组件逻辑 import { appRouter } from '@/server/router'; // 导入你的tRPC路由 import { createTRPCContext } from '@/server/trpc'; // 导入你的tRPC上下文创建函数 const PortfolioSection = async () => { // 创建服务端上下文 const ctx = await createTRPCContext(); // 创建tRPC服务端调用器 const trpcServerCaller = appRouter.createCaller(ctx); // 直接调用接口 const getAllData = await trpcServerCaller.projects.getAll(); console.log(getAllData); return ( // 你的JSX渲染逻辑不变 ); };
3. 修复代码中的潜在问题
- 优化空值处理:把
getAllData && getAllData?.data?.map(...) || <></>改为getAllData?.data?.map(...) || [],避免返回undefined或空片段导致的渲染异常:{getAllData?.data?.map(({ attributes }: any, projIdx: any) => ( // 项目卡片JSX )) || []} - 增加正则匹配容错:在解析
attributes.links时,添加空值判断,避免格式错误导致的崩溃:attributes.links.split(', ').map((link: any, linkIdx: any) => { const matchResult = link.match(/(?<=\[).+(?=\))/); if (!matchResult) return null; // 跳过格式错误的链接 const [type, href] = matchResult[0].split(']('); // 后续Link渲染逻辑 }) - 检查环境变量:确认
env.NEXT_PUBLIC_STRAPI_URI正确获取,Next.js中应使用process.env.NEXT_PUBLIC_STRAPI_URI(需在.env文件中配置)。
验证
修改后,重新运行项目,服务端组件会在服务器端完成数据获取和渲染,不会返回Promise,即可解决错误。
内容的提问来源于stack exchange,提问作者Daisho Arch
相关产品推荐
相关产品推荐

