T3栈中Prisma查询结果无法传递给React组件的问题排查
问题描述
使用T3栈(create-t3-app),包含TypeScript、Prisma和Next.js,在获取查询结果并传递给React组件时遇到类型不匹配错误。
Prisma Article模型
model Article { id String @id @default(cuid()) organizationId String title String subtitle String? content String @db.Text publishDate DateTime? endDate DateTime? }
tRPC路由定义
export const articleRouter = createTRPCRouter({ getById: publicProcedure.input(z.string()).query(async ({ ctx, input }) => { const x = await ctx.prisma.article.findFirst({ where: { id: input, }, }); return x; }), });
组件调用代码
const article = api.article.getById.useQuery("clkem2k2m0000uf2klvuu7bfl"); ... <ArticleCard color="blue" article={article} />
ArticleCard组件代码
import { Article } from "@prisma/client"; export interface ArticleProps { article: Article; color: string; } export default function ArticleCard(props: ArticleProps) { return ( <> <Container> <Box> INSIDE THE BOX <Card className="p-2"> INSIDE THE CARD <Typography variant="h3" className="text-blue-500"> {props.article.title} Yay! {props.color} </Typography> {props.article?.subtitle ? ( <Typography variant="h5">{props.article?.subtitle}</Typography> ) : ( <> </> )} <Typography variant="body1">{props.article.content}</Typography> </Card> </Box> </Container> </> ); }
报错信息
Type 'UseTRPCQueryResult<(GetResult<{ id: string; organizationId: string; title: string; subtitle: string | null; content: string; publishDate: Date | null; endDate: Date | null; }, unknown> & {}) | null, TRPCClientErrorLike<...>>' is not assignable to type 'GetResult<{ id: string; organizationId: string; title: string; subtitle: string | null; content: string; publishDate: Date | null; endDate: Date | null; }, unknown> & {}'. Type 'TRPCHookResult & QueryObserverRefetchErrorResult<(GetResult<{ id: string; organizationId: string; title: string; subtitle: string | null; content: string; publishDate: Date | null; endDate: Date | null; }, unknown> & {}) | null, TRPCClientErrorLike<...>>' is not assignable to type 'GetResult<{ id: string; organizationId: string; title: string; subtitle: string | null; content: string; publishDate: Date | null; endDate: Date | null; }, unknown> & {}'. Type 'TRPCHookResult & QueryObserverRefetchErrorResult<(GetResult<{ id: string; organizationId: string; title: string; subtitle: string | null; content: string; publishDate: Date | null; endDate: Date | null; }, unknown> & {}) | null, TRPCClientErrorLike<...>>' is missing the following properties from type 'GetResult<{ id: string; organizationId: string; title: string; subtitle: string | null; content: string; publishDate: Date | null; endDate: Date | null; }, unknown>': title, id, content, organizationId, and 3 more.ts(2322) articleCard.tsx(5, 3): The expected type comes from property 'article' which is declared here on type 'IntrinsicAttributes & ArticleProps' (property) ArticleProps.article: GetResult<{ id: string; organizationId: string; title: string; subtitle: string | null; content: string; publishDate: Date | null; endDate: Date | null; }, unknown> & {}
疑问
- 此场景下findFirst()返回的数据类型是什么?
- 如何通过props正确将其传递给函数组件?
解答
1. findFirst() 返回的类型
Prisma的findFirst()方法返回的类型是Article | null——即你定义的Prisma模型对应的实体类型,或者null(当未找到匹配记录时)。
你遇到的类型错误并非来自findFirst(),而是tRPC的useQuery钩子返回的不是直接的查询结果:useQuery返回的是一个包含查询状态的对象(UseTRPCQueryResult类型),其中data字段才是实际的Article数据,同时还包含isLoading、error等状态属性。你直接把整个useQuery返回值传给组件,自然会出现类型不匹配。
2. 正确传递props的方法
需要从useQuery返回值中提取data字段,同时处理加载、错误以及数据为null的情况:
修改调用代码
const { data: article, isLoading, error } = api.article.getById.useQuery("clkem2k2m0000uf2klvuu7bfl"); // 处理加载状态 if (isLoading) return <div>加载中...</div>; // 处理错误状态 if (error) return <div>加载失败:{error.message}</div>; // 处理未找到文章的情况 if (!article) return <div>未找到对应文章</div>; // 此时article类型为Article,符合组件props要求 return <ArticleCard color="blue" article={article} />;
可选:允许组件接收null值
如果你希望组件自行处理数据为null的场景,可以调整props类型:
export interface ArticleProps { article: Article | null; color: string; }
注意组件内部访问props.article.title这类非可选属性时,要先确保article不为null,避免运行时错误。
内容的提问来源于stack exchange,提问作者mateoc15
相关产品推荐
相关产品推荐

