珠海网站建设最新报价,wordpress 广告 插件下载,wordpress多租户,中山营销型网站原文链接 CSDN 的排版/样式可能有问题#xff0c;去我的博客查看原文系列吧#xff0c;觉得有用的话#xff0c;给我的库点个star#xff0c;关注一下吧 上一篇【Next.js 项目实战系列】03-查看 Issue
修改 Issue
添加修改 Button
本节代码链接
安装 Radix UI 的 Ra…原文链接 CSDN 的排版/样式可能有问题去我的博客查看原文系列吧觉得有用的话给我的库点个star关注一下吧 上一篇【Next.js 项目实战系列】03-查看 Issue
修改 Issue
添加修改 Button
本节代码链接
安装 Radix UI 的 Radix Ui Icons
npm i radix-ui/react-icons# /app/issues/[id]/page.tsx...const IssueDeatilPage async ({ params }: Props) {...return (// 添加一个 Grid 以分列显示设置 initial 为 1在移动设备为每页 1 栏平板以上则 2 栏Grid columns{{ initial: 1, md: 2 }} gap5BoxHeading ash2{issue.title}/Heading.../Box{/*添加一个 Button 用于编辑*/}BoxButtonPencil2Icon /Link href{/issues/${issue.id}/edit}Edit Issue/Link/Button/Box/Grid);};export default IssueDeatilPage;Single Responsbility Principle
本节代码链接 Software entities should have a single responsibility 重构 /app/issues/[id]/page.tsx 以应用 SRP
page.tsxIssueDetails.tsxEditIssueButton.tsx
# /app/issues/[id]/page.tsximport prisma from /prisma/client;
import { Box, Grid } from radix-ui/themes;
import { notFound } from next/navigation;
import EditIssueButton from ./EditIssueButton;
import IssueDetails from ./IssueDetails;interface Props {params: { id: string };
}
const IssueDeatilPage async ({ params }: Props) {const issue await prisma.issue.findUnique({where: { id: parseInt(params.id) },});if (!issue) notFound();return (Grid columns{{ initial: 1, md: 2 }} gap5BoxIssueDetails issue{issue} //BoxBoxEditIssueButton issueId{issue.id} //Box/Grid);
};
export default IssueDeatilPage;# /app/issues/[id]/IssueDetails.tsximport { IssueStatusBadge } from /app/components;
import { Issue } from prisma/client;
import { Card, Flex, Heading, Text } from radix-ui/themes;
import ReactMarkdown from react-markdown;const IssueDetails ({ issue }: { issue: Issue }) {return (Heading ash2{issue.title}/HeadingFlex gap3 my5IssueStatusBadge status{issue.status}/IssueStatusBadgeText{issue.createdAt.toDateString()}/Text/FlexCard classNameproseReactMarkdown{issue.description}/ReactMarkdown/Card/);
};
export default IssueDetails;
# /app/issues/[id]/EditIssueButton.tsximport { Pencil2Icon } from radix-ui/react-icons;
import { Button } from radix-ui/themes;
import Link from next/link;const EditIssueButton ({ issueId }: { issueId: number }) {return (ButtonPencil2Icon /Link href{/issues/${issueId}/edit}Edit Issue/Link/Button);
};
export default EditIssueButton;
修改 Issue
页面
本节代码链接
我们可以像这样构建文件结构在 Issue 目录下创建 _components 以放置该目录下需要重复使用的组件文件夹名前添加下划线就可以把这个文件夹从路由中移除
└─issues│ IssueActions.tsx│ loading.tsx│ page.tsx│├─new│ loading.tsx│ page.tsx│├─[id]│ │ EditIssueButton.tsx│ │ IssueDetails.tsx│ │ loading.tsx│ │ page.tsx│ ││ └─Edit│ page.tsx│└─_componentsIssueForm.tsx将之前的 new/page.tsx 封装为一个组件并添加一个可选参数以初始化
# /app/issues/_components/IssueForm.tsx...import { Issue } from prisma/client;...// 添加一个可选参数 issue 类型为之前 prisma 中的 Issue
- const IssueForm () {const IssueForm ({ issue }: { issue?: Issue }) {...return (div classNamemax-w-xl prose...TextField.RootTextField.Input// 将该字段初始化为 issue.title (若传入 issue)defaultValue{issue?.title}placeholderTitle{...register(title)}//TextField.RootErrorMessage{errors.title?.message}/ErrorMessageController// 将该字段初始化为 issue.description (若传入 issue)defaultValue{issue?.description}namedescriptioncontrol{control}render{({ field }) (SimpleMDE placeholderDescription {...field} /)}/.../div);};export default IssueForm;API
本节代码链接
# /app/api/issues/[id]/route.tsximport { issueSchema } from /app/validationSchema;
import { NextRequest, NextResponse } from next/server;
import prisma from /prisma/client;export async function PATCH(request: NextRequest,{ params }: { params: { id: string } }
) {const body await request.json();const validation issueSchema.safeParse(body);if (!validation.success)return NextResponse.json(validation.error.format(), { status: 400 });const issue await prisma.issue.findUnique({where: { id: parseInt(params.id) },});if (!issue)return NextResponse.json({ error: Invalid Issue }, { status: 404 });const updatedIssue await prisma.issue.update({where: { id: issue.id },data: { title: body.title, description: body.description },});return NextResponse.json(updatedIssue, { status: 200 });
}连接
本节代码链接
# /app/issues/_components/IssueForm.tsxconst IssueForm ({ issue }: { issue?: Issue }) {...return (...formclassNamespace-y-3onSubmit{handleSubmit(async (data) {try {setSubmitting(true);// 判断是否传入了 issue若有传入则是 Update若无则是 newif (issue) await axios.patch(/api/issues/ issue.id, data);
- await axios.post(/api/issues, data);else await axios.post(/api/issues, data);router.push(/issues);} ...})}...Button disabled{isSubmitting}{issue ? Update Issue : Submit New Issue}{ }{isSubmitting Spinner /}/Button/form...);};export default IssueForm;Caching
本节代码链接
NextJS Route Segment Config
Data Cache: When we fetch data using fetch()Stored in the file systemPermanent unitl we redeployfetch(.,{cache: no-store})fetch(.,{revalidata: 3600})Full Route Cache Used to store the output of statically renderd routesRouter Cache (Client-side Cache) To store the payload of pages in browserLasts for a sessionGets refreshed when we reload
提升 Loading 体验
本节代码链接
由于我们要在多个地方用到 IssueForm 的 Skeleton我们可以将其封装到一个组件里然后在需要的地方调用。其次对于静态的页面可以直接使用 loading.tsx但是对于需要用到 dynamic 函数的页面应该用另一种方法
IssueFormSkeleton.tsxpage.tsxloading.tsx
# /app/issues/_components/IssueFormSkeleton.tsximport { Skeleton } from /app/components;
import { Box } from radix-ui/themes;const IssueFormSkeleton () {return (Box classNamemax-w-xlSkeleton height2rem /Skeleton height20rem //Box);
};
export default IssueFormSkeleton;
# /app/issues/[id]/edit/page.tsximport prisma from /prisma/client;
import dynamic from next/dynamic;
import { notFound } from next/navigation;
import IssueFormSkeleton from ./loading;const IssueForm dynamic(() import(/app/issues/_components/IssueForm), {ssr: false,loading: () IssueFormSkeleton /,
});interface Props {params: { id: string };
}const EditIssuePage async ({ params }: Props) {const issue await prisma.issue.findUnique({where: { id: parseInt(params.id) },});if (!issue) notFound();return IssueForm issue{issue} /;
};
export default EditIssuePage;
# /app/issues/[id]/edit/loading.tsximport IssueFormSkeleton from /app/issues/_components/IssueFormSkeleton;
export default IssueFormSkeleton; CSDN 的排版/样式可能有问题去我的博客查看原文系列吧觉得有用的话给我的库点个star关注一下吧 下一篇讲删除 Issue
下一篇【Next.js 项目实战系列】05-删除 Issue