tRPC v10报错:Query data cannot be undefined 求助
解决tRPC v10中"Query data cannot be undefined"报错问题
错误原因分析
你遇到的Query data cannot be undefined报错,核心原因是开启SSR后,客户端React Query在hydration阶段无法获取到服务器端预取的数据,或者React Query的严格模式默认不允许查询数据为undefined。结合你的代码,主要问题集中在SSR配置和数据预取环节。
具体解决方案
1. 调整Query Client默认配置
在utils/trpc.ts中启用并修改queryClientConfig,关闭严格模式或允许数据为undefined:
export const trpc = createTRPCNext<AppRouter, SSRContext>({ config({ ctx }) { return { transformer: superjson, links: [ httpBatchLink({ url: `${getBaseUrl()}/api/trpc`, }), ], // 启用并修改查询客户端配置 queryClientConfig: { defaultOptions: { queries: { staleTime: 60, // 关闭严格模式,允许数据为undefined strict: false, // 可选:关闭自动重试,减少调试干扰 retry: false, }, }, }, headers() { // 原headers逻辑保持不变 if (ctx?.req) { const { connection: _connection, ...headers } = ctx.req.headers; return { ...headers, "x-ssr": "1", }; } return {}; }, }; }, ssr: true, });
2. 为页面添加服务器端数据预取
因为你开启了ssr: true,必须在服务器端预取页面所需的所有tRPC查询数据,确保客户端hydration时能拿到数据。修改pages/test.tsx:
import React from "react"; import { NextPage, GetServerSideProps } from "next"; import { trpc } from "@/utils/trpc"; const TestPage: NextPage = () => { const helloNoArgs = trpc.authy.hello.useQuery(); const helloWithArgs = trpc.authy.hello.useQuery({ text: "client" }); const greeting = trpc.greeting.useQuery(); return ( <div> <h1>Hello World Example</h1> <ul> <li> helloNoArgs ({helloNoArgs.status}):{" "} <pre>{JSON.stringify(helloNoArgs.data, null, 2)}</pre> </li> <li> helloWithArgs ({helloWithArgs.status}):{" "} <pre>{JSON.stringify(helloWithArgs.data, null, 2)}</pre> </li> <li> greeting ({greeting.status}):{" "} <pre>{JSON.stringify(greeting.data, null, 2)}</pre> </li> </ul> </div> ); }; // 添加服务器端预取逻辑 export const getServerSideProps: GetServerSideProps = async (ctx) => { const trpcCaller = trpc.createCaller(ctx); // 预取页面所有用到的查询 await Promise.all([ trpcCaller.authy.hello(), trpcCaller.authy.hello({ text: "client" }), trpcCaller.greeting(), ]); return { props: {} }; }; export default TestPage;
3. 简化Input Schema(可选)
server/router/authy.ts中的input schema存在冗余的.nullish().optional(),可以简化为:
.input(z.object({ text: z.string().nullish() }).optional())
或者更简洁的写法:
.input(z.object({ text: z.string() }).nullish())
4. 验证API路由配置
确保pages/api/trpc/[trpc].ts存在且配置正确,这是tRPC客户端与服务器通信的核心入口:
import { createNextApiHandler } from "@trpc/server/adapters/next"; import { appRouter } from "@/server/router/_app"; import { createContext } from "@/server/trpc"; export default createNextApiHandler({ router: appRouter, createContext, });
生效原理
- 关闭React Query的
strict模式,会解除"数据不能为undefined"的限制,避免hydration阶段的报错; - 服务器端预取数据后,tRPC会自动将数据同步到客户端的Query Client,确保客户端渲染时能直接拿到数据;
- 简化schema避免不必要的类型解析歧义,减少潜在的序列化问题;
- 正确的API路由是tRPC客户端与服务器建立通信的基础,缺失或配置错误会导致所有查询失败。
内容的提问来源于stack exchange,提问作者wongx
相关产品推荐
相关产品推荐

