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

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> & {}
疑问
  1. 此场景下findFirst()返回的数据类型是什么?
  2. 如何通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 06:35:20