Next.js项目实践(七)– 分配问题给用户

本文实现用户问题分配。


构建分配问题的用户选择组件

查看对照Radix UI 官方网站的Select组件的示例,创建 AssigneeSelect.tsx,位于 /app/issues/[id]目录下。

"use client";
​
import React from "react";
import { Select } from "@radix-ui/themes";
​
const AssigneeSelect = () => {
  return (
    <Select.Root>
      <Select.Trigger placeholder="Assign..."></Select.Trigger>
      <Select.Content>
        <Select.Group>
          <Select.Label>Suggestions</Select.Label>
          <Select.Item value="1">Kelemi</Select.Item>
        </Select.Group>
      </Select.Content>
    </Select.Root>
  );
};
​
export default AssigneeSelect;
​

接着,在详细页面中调用 AssigneeSelect组件。

查看网页。

提交Git,命名:Build the assignee select component.


填充用户选择组件

我们从数据库获取用户列表并填充用户选择组件。先创建API, /app/api/新建users目录,再创建route.tsx文件。

import prisma from "@/prisma/client";
import { NextRequest, NextResponse } from "next/server";
​
export async function GET(request: NextRequest) {
  const users = await prisma.user.findMany();
  return NextResponse.json(users);
}

然后在AssigneeSelect中调用该API获取用户列表并填充选择组件。我们使用useEffect调用后端数据库,然后用users.map填充选择组件。之前《React入门》系列里有过介绍。

查看网页,选择组件已由数据表里的用户来填充了。

提交Git,命名:Polulate the asignee select component.


设置React Query

React Query的好处在《React中级教程》已详细介绍过,我们用React Query来代替useEffect. 先设置。

安装:npm i @tanstack/react-query@4.35.3

在app目录新建QueryClientProvider.tsx文件。需要改成客户端组件(“use client”;)

"use client";
​
import {
  QueryClient,
  QueryClientProvider as ReactQueryClientProvider,
} from "@tanstack/react-query";
import { PropsWithChildren } from "react";
​
const QueryClientProvider = ({ children }: PropsWithChildren) => {
  const queryClient = new QueryClient();
  return (
    <ReactQueryClientProvider client={queryClient}>
      {children}
    </ReactQueryClientProvider>
  );
};
​
export default QueryClientProvider;

lauout.tsx调用QueryClientProvider。

提交Git,命名:Set up React Query.


使用 React Query获取数据

去掉useEffect和useState,用ReactQuery代替。下面代码是ReactQuery的常规用法, 加颜色的各行是修改部分。

提交Git,命名:Fetch data with React Query.


将分配的问题添加到Prisma

在schema.prisma里给Issue模型添加User的关联字段assignedToUserId,并设置关联。

再进行迁移:npx prisma migrate dev

检查数据表Issue已增加相应字段。

提交Git,命名:Add assigned issues to prisma schema.


实现API

增强 /api/issues/[id]的PATCH实现,来允许更新Issue的assignedToUserId。之前的IssueSchema是验证title和description的,我们再新建一个schema,允许更新单个或某几个属性。

新建PatchIssueSchema,验证3个属性title,description和 assignedToUserId,都是可选属性【optional()】,assignedToUserId还允许设置为null【nullable()】。

//  app/validationSchemas.ts
......
​
export const patchIssueSchema = z.object({
  title: z.string().min(1, "Title is required.").max(255).optional(),
  description: z.string().min(1, "Description is required.").max(65535).optional(),
  assignedToUserId: z.string().min(1, "assignedToUserId is required.").max(255).optional().nullable(),
});
​

修改 API。

提交Git,命名:Enhance the API to assign issues.


将问题分配给用户

修改AssigneeSelect.tsx,给Select组件的onValueChange添加处理,通API更新assignedToUserId,另外添加Select一个Item,允许设置回null。

上面代码,AssigneeSelect组件需要传入issue对象,需要在IssueDetailPage里传过去。

提交Git,命名:Assign an issue to a user.


显示 Toast 通知

安装:npm i react-hot-toast@2.4.1

再在AssigneeSelect.tsx中使taost。

我们故意写错 api端点,查看页面。

提交Git,命名:Show toast notifications.


重构AssigneeSelect组件

重构AssigneeSelect组件,onValueChange内联逻辑稍有点长,提取成assignIssue放在渲染组件的外部。另外,useQuery也提取成自定义Hook ,useUsers放在文件最后,这样更清晰。

注意,我们没把重构的函数放在另外文件,只放在同一文件里,这要看实际情况,目录我们的函数是没有必须另起文件的。

提交Git,命名:Refactor AssigneeSelect component.


小结

本文实现了将问题分配给用户的功能。

下一篇实现筛选、排序、分页等功能。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注