我使用的是typescript、next.js、react、trpc和prisma。在一个顶级组件中,我调用了一个trpc函数,该函数获取与另一个表具有多对多关系的表的所有行。在findMany函数中,我包含(连接)另一个表。在顶层组件( Jmeter 板)中,我成功地取回了数据,并将其Map到另一个组件(卡)。所有这些都是为了显示数据而“工作”的,没有任何东西在客户端上“中断”。但是,我确实有一个类型脚本错误,它破坏了我的部署linting。
错误:enter image description here
Jmeter 板组件:
import { type NextPage } from "next";
import React from "react";
import Card from "./Card";
import CreateNewCard from "~/components/CreateNewCard";
import { api } from "~/utils/api";
import type { Packet } from "./Card";
const Dashboard = (props: { organization_id: string }) => {
const { data } = api.example.getAllUserPackets.useQuery({
organization_id: props.organization_id,
});
return (
<div className="min-w-screen flex min-h-screen">
<div className="w-full">
<div className="">Dashboard</div>
<div className="flex flex-grow flex-wrap justify-evenly gap-8">
<CreateNewCard />
{!data ? (
<div>Sorry there seems to be no projects for this organization</div>
) : (
data.map((packet) => {
//console.log("PACKET: ", packet);
return <Card packet={packet} key={packet.id} />;
})
)}
</div>
</div>
</div>
);
};
export default Dashboard;
卡组件:
import Link from "next/link";
import { useState } from "react";
import { api } from "~/utils/api";
import toast from "react-hot-toast";
import { truncatedName } from "../helper/stringManipulations";
const Card = (props: { packet: Packet }) => {
const [cardData, setCardData] = useState(props.packet);
const [isEdittingTitle, toggleIsEditing] = useState(false);
const {
id,
deadline,
progress_indication,
tags,
is_priority_high,
author_id,
card_author_name,
} = cardData;
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setCardData((prev) => {
return {
...prev,
[e.target.name]: e.target.value,
};
});
};
const { mutate, isLoading: isEditing } = api.example.editCard.useMutation({
onSuccess: () => {
// do somthing
},
onError: (e) => {
const errorMessage = e.data?.zodError?.fieldErrors.content;
if (errorMessage && errorMessage[0]) {
toast.error(errorMessage[0], {
duration: 3000,
position: "top-center",
// Custom Icon
icon: "🙀",
// Change colors of success/error/loading icon
iconTheme: {
primary: "#000",
secondary: "#232323",
},
});
} else {
toast.error("Failed to post. Sorry, please post again later.", {
duration: 3000,
position: "bottom-center",
// Custom Icon
icon: "🙀",
// Change colors of success/error/loading icon
iconTheme: {
primary: "#000",
secondary: "#232323",
},
});
}
},
});
const deselect = () => {
document.querySelector("p")?.toggleAttribute("focus");
};
return (
<div
onClick={(e) => {
isEdittingTitle ? toggleIsEditing(false) : null;
}}
className="relative w-80 max-w-full content-end rounded-3xl bg-purple-500 px-8 py-4 text-white subpixel-antialiased shadow-xl hover:translate-y-1 hover:bg-purple-600 hover:shadow-sm"
>
<div className="max-w-md">
<div className="flex justify-between">
<div className="flex justify-between gap-4">
<p className="font-bold">{is_priority_high && "High"} Priority</p>
</div>
<Link
href="/packet/project-id"
className="rounded-lg border px-4 py-2"
>
Go To Project
</Link>
</div>
<div className="mt-2 flex flex-col">
{!isEdittingTitle ? (
<p
onClick={(e) => {
toggleIsEditing(!isEdittingTitle);
}}
className="edit-input w-full overflow-visible whitespace-pre-wrap bg-transparent text-[26px] font-bold backdrop:max-h-min"
>
{cardData.title}
</p>
) : (
<textarea
name="title"
onFocus={(e) => e.target.select()}
autoFocus={true}
value={cardData.title}
onKeyDown={(e) => {
if (e.key === "Enter") {
mutate({ id, column: "title", content: cardData["title"] });
toggleIsEditing(!isEdittingTitle);
}
}}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
handleChange(e);
}}
className="resize-none bg-transparent text-[26px]"
/>
)}
<p className="">Created By: {card_author_name}</p>
<div className="flex flex-row">
<p className="pr-2 font-bold">Due</p>
<p className=" ">{deadline?.toDateString()}</p>
</div>
<div className="py-6 text-[20px]">
{!tags ? (
<div></div>
) : (
tags.map((tag) => {
return <p key={tag.id}>{tag.tagName}</p>;
})
)}
</div>
</div>
<div className="flex h-full w-full items-end justify-between">
<div className="w-1/2">
<p className="text-[20px] ">{progress_indication}</p>
</div>
<div className=" flex- flex w-2/6 justify-evenly gap-0 self-end">
{/* {members.map((member) => {
return (
<Link key={member.name} href={`/team/${member.name.trim()}`}>
<div
className={` -mx-4 flex h-12 w-12 items-center justify-evenly gap-0 rounded-full hover:-translate-x-1 hover:-translate-y-1 ${member.color} p-2 text-xl`}
>
<p className={""}>{truncatedName(member.name)}</p>
</div>
</Link>
);
})} */}
</div>
</div>
</div>
</div>
);
};
export default Card;
export type Tag = {
id: number;
tagName: string;
};
export type Packet = {
id: string;
title: string;
description: string;
author_id: string;
deadline: Date;
createdAt: Date;
updatedAt: Date;
is_priority_high: boolean;
progress_indication: string;
card_author_name: string;
organization_id: string;
is_org_admin: boolean;
tags: Tag[];
};
TRPC中的功能-查找共享用户“组织ID”的所有“数据包”
getAllUserPackets: publicProcedure
.input(z.object({organization_id: z.string()}))
.query(async ({ctx, input}) => {
const data = await ctx.prisma.packet.findMany({where: {organization_id: input.organization_id}, include: {tags: true}} )
return data
}),
Prisma型号
model Packet {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
card_author_name String?
author_id String
organization_id String
is_org_admin Boolean? @default(false)
title String
description String
project_leader_id String?
progress_indication Progress @default(CREATED)
is_priority_high Boolean? @default(false)
deadline DateTime @default(now())
tags Tag[]
@@index([author_id])
}
model Tag {
id String @id @default(cuid())
tagName String
packet Packet[]
}
我尝试添加反映数据的类型(在Card Component的底部看到),并确保数据库中可能需要的数据不会因“不在前端”而导致问题。我给出了Card组件及其期望的 prop ,以及Card JSX如何在Dashboard组件中接收数据。
我对 typescript 和Prisma的不熟悉是罪魁祸首,但感谢任何帮助学习我在这里错过了什么。
1条答案
按热度按时间luaexgnf1#
您不应该手动为
prisma.schema
模型创建类型,因为Prisma会自动或使用npx prisma generate
命令手动创建它们。因此,要解决这个问题,您需要从
Card.tsx
中删除已经手动定义的类型,并从@prisma/client
中导入自动创建的类型。由于Prisma Client不会自动处理类型中的关系,因此您需要使用以下代码来使其工作:然后你可以使用类型
PacketWithTags
作为你的组件props类型Card.tsx
:)