自贡市建设局网站2016网站设计
自贡市建设局网站,2016网站设计,江苏苏州有什么好玩的,免费网络正能量直接进入文章目录 一、项目起航#xff1a;项目初始化与配置二、React 与 Hook 应用#xff1a;实现项目列表三、TS 应用#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook… 文章目录 一、项目起航项目初始化与配置二、React 与 Hook 应用实现项目列表三、TS 应用JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook路由与 URL 状态管理八、用户选择器与项目编辑功能九、深入React 状态管理与Redux机制十、用 react-query 获取数据管理缓存十一、看板页面及任务组页面开发1~34~67.编辑任务功能8.看板和任务删除功能 学习内容来源React React Hook TS 最佳实践-慕课网 相对原教程我在学习开始时2023.03采用的是当前最新版本
项版本react react-dom^18.2.0react-router react-router-dom^6.11.2antd^4.24.8commitlint/cli commitlint/config-conventional^17.4.4eslint-config-prettier^8.6.0husky^8.0.3lint-staged^13.1.2prettier2.8.4json-server0.17.2craco-less^2.0.0craco/craco^7.1.0qs^6.11.0dayjs^1.11.7react-helmet^6.1.0types/react-helmet^6.1.6react-query^6.1.0welldone-software/why-did-you-render^7.0.1emotion/react emotion/styled^11.10.6
具体配置、操作和内容会有差异“坑”也会有所不同。。。 一、项目起航项目初始化与配置 一、项目起航项目初始化与配置 二、React 与 Hook 应用实现项目列表 二、React 与 Hook 应用实现项目列表 三、TS 应用JS神助攻 - 强类型 三、 TS 应用JS神助攻 - 强类型 四、JWT、用户认证与异步请求 四、 JWT、用户认证与异步请求(上) 四、 JWT、用户认证与异步请求(下) 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(上) 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下) 六、用户体验优化 - 加载中和错误状态处理 六、用户体验优化 - 加载中和错误状态处理(上) 六、用户体验优化 - 加载中和错误状态处理(中) 六、用户体验优化 - 加载中和错误状态处理(下) 七、Hook路由与 URL 状态管理 七、Hook路由与 URL 状态管理(上) 七、Hook路由与 URL 状态管理(中) 七、Hook路由与 URL 状态管理(下) 八、用户选择器与项目编辑功能 八、用户选择器与项目编辑功能(上) 八、用户选择器与项目编辑功能(下) 九、深入React 状态管理与Redux机制 九、深入React 状态管理与Redux机制(一) 九、深入React 状态管理与Redux机制(二) 九、深入React 状态管理与Redux机制(三) 九、深入React 状态管理与Redux机制(四) 九、深入React 状态管理与Redux机制(五) 十、用 react-query 获取数据管理缓存 十、用 react-query 获取数据管理缓存上 十、用 react-query 获取数据管理缓存下 十一、看板页面及任务组页面开发
1~3 十一、看板页面及任务组页面开发一 4~6 十一、看板页面及任务组页面开发二 7.编辑任务功能
接下来新建编辑任务的组件
先准备好调用编辑任务接口和获取任务详情的 Hook编辑 src\utils\task.ts
...
import { useAddConfig, useEditConfig } from ./use-optimistic-options;export const useEditTask (queryKey: QueryKey) {const client useHttp();return useMutation((params: PartialTask) client(tasks/${params.id}, {method: PATCH,data: params,}),useEditConfig(queryKey));
};export const useTask (id?: number) {const client useHttp();return useQueryTask([task, id], () client(tasks/${id}), {enabled: Boolean(id),});
};编辑 src\screens\ViewBoard\utils.ts(新增 useTasksModal)
...
// import { useDebounce } from utils;
import { useTask } from utils/task;
...export const useTasksSearchParams () {const [param] useUrlQueryParam([name,typeId,processorId,tagId,]);const projectId useProjectIdInUrl();// const debouncedName useDebounce(param.name)return useMemo(() ({projectId,typeId: Number(param.typeId) || undefined,processorId: Number(param.processorId) || undefined,tagId: Number(param.tagId) || undefined,// name: debouncedName,name: param.name,}),// [projectId, param, debouncedName][projectId, param]);
};...export const useTasksModal () {const [{ editingTaskId }, setEditingTaskId] useUrlQueryParam([editingTaskId])const { data: editingTask, isLoading } useTask(Number(editingTaskId))const startEdit useCallback((id: number) {setEditingTaskId({editingTaskId: id})}, [setEditingTaskId])const close useCallback(() {setEditingTaskId({editingTaskId: })}, [setEditingTaskId])return {editingTaskId,editingTask,startEdit,close,isLoading}
}视频中使用 useDebounce 使得完全停止输入后才开始搜索避免输入过程中频繁搜索造成系统资源浪费且影响用户体验博主这样更改后中文输入法无法正常使用。。。后续再解决 新建组件src\screens\ViewBoard\components\taskModal.tsx
import { useForm } from antd/lib/form/Form
import { useTasksModal, useTasksQueryKey } from ../utils
import { useEditTask } from utils/task
import { useEffect } from react
import { Form, Input, Modal } from antd
import { UserSelect } from components/user-select
import { TaskTypeSelect } from components/task-type-selectconst layout {labelCol: {span: 8},wrapperCol: {span: 16}
}export const TaskModal () {const [form] useForm()const { editingTaskId, editingTask, close } useTasksModal()const { mutateAsync: editTask, isLoading: editLoading } useEditTask(useTasksQueryKey())const onCancel () {close()form.resetFields()}const onOk async () {await editTask({...editingTask, ...form.getFieldsValue()})close()}useEffect(() {form.setFieldsValue(editingTask)}, [form, editingTask])return ModalforceRender{true}onCancel{onCancel}onOk{onOk}okText{确认}cancelText{取消}confirmLoading{editLoading}title{编辑任务}open{!!editingTaskId}Form {...layout} initialValues{editingTask} form{form}Form.Itemlabel{任务名}name{name}rules{[{ required: true, message: 请输入任务名 }]}Input //Form.ItemForm.Item label{经办人} name{processorId}UserSelect defaultOptionName{经办人} //Form.ItemForm.Item label{类型} name{typeId}TaskTypeSelect //Form.Item/Form/Modal
}注意与 Drawer 一样在Modal 组件中使用通过 useForm() 提取的 form 绑定的 Form 时需要添加 forceRender 属性否则在页面打开时绑定不到会有报错参见【实战】React 实战项目常见报错 —— Instance created by ‘useForm’ is not connected to any Form element. Forget… 编辑src\screens\ViewBoard\index.tsx引入 TaskModal
...
import { TaskModal } from ./components/taskModal;export const ViewBoard () {...return (ViewContainer...TaskModal//ViewContainer);
};
...编辑src\screens\ViewBoard\components\ViewboardCloumn.tsx引入 useTasksModal 使得点击 任务卡片 可以打开 TaskModal 进行编辑
...
import { useTasksModal, useTasksSearchParams } from ../utils;
...export const ViewboardColumn ({ viewboard }: { viewboard: Viewboard }) {...const { startEdit } useTasksModal()return (Container...TasksContainer{tasks?.map((task) (Card onClick{() startEdit(task.id)} style{{ marginBottom: 0.5rem, cursor: pointer }} key{task.id}.../Card))}.../TasksContainer/Container);
};
...查看功能和效果点击 任务卡片 后 TaskModal 出现编辑并确认后即可看到修改后的任务用了乐观更新完全无感
8.看板和任务删除功能
接下来先实现一个小功能搜索结果中关键字高亮
新建 src\screens\ViewBoard\components\mark.tsx
export const Mark ({name, keyword}: {name: string, keyword: string}) {if(!keyword) {return {name}/}const arr name.split(keyword)return {arr.map((str, index) span key{index}{str}{index arr.length -1 ? null : span style{{ color: #257AFD }}{keyword}/span}/span)}/
}编辑 src\screens\ViewBoard\components\ViewboardCloumn.tsx引入 Task 并将 TaskCard 单独提取出来
...
import { Task } from types/Task;
import { Mark } from ./mark;...const TaskCard ({task}: {task: Task}) {const { startEdit } useTasksModal();const { name: keyword } useTasksSearchParams()return CardonClick{() startEdit(task.id)}style{{ marginBottom: 0.5rem, cursor: pointer }}key{task.id}pMark keyword{keyword} name{task.name}//pTaskTypeIcon id{task.id} //Card
}export const ViewboardColumn ({ viewboard }: { viewboard: Viewboard }) {const { data: allTasks } useTasks(useTasksSearchParams());const tasks allTasks?.filter((task) task.kanbanId viewboard.id);return (Containerh3{viewboard.name}/h3TasksContainer{tasks?.map((task) TaskCard task{task}/)}CreateTask kanbanId{viewboard.id} //TasksContainer/Container);
};
...查看效果 下面开始开发删除功能
编辑 src\utils\viewboard.ts创建并导出 useDeleteViewBoard
...
export const useDeleteViewBoard (queryKey: QueryKey) {const client useHttp();return useMutation((id?: number) client(kanbans/${id}, {method: DELETE,}),useDeleteConfig(queryKey));
};编辑 src\screens\ViewBoard\components\ViewboardCloumn.tsx
...
import { Button, Card, Dropdown, MenuProps, Modal, Row } from antd;
import { useDeleteViewBoard } from utils/viewboard;...export const ViewboardColumn ({ viewboard }: { viewboard: Viewboard }) {const { data: allTasks } useTasks(useTasksSearchParams());const tasks allTasks?.filter((task) task.kanbanId viewboard.id);return (ContainerRowh3{viewboard.name}/h3More viewboard{viewboard}//RowTasksContainer{tasks?.map((task) TaskCard task{task}/)}CreateTask kanbanId{viewboard.id} //TasksContainer/Container);
};const More ({ viewboard }: { viewboard: Viewboard }) {const {mutateAsync: deleteViewBoard} useDeleteViewBoard(useViewBoardQueryKey())const startDelete () {Modal.confirm({okText: 确定,cancelText: 取消,title: 确定删除看板吗,onOk() {deleteViewBoard(viewboard.id)}})}const items: MenuProps[items] [{key: 1,label: 删除,onClick: startDelete,},];return Dropdown menu{{ items }}Button typelink onClick{(e) e.preventDefault()}.../Button/Dropdown
}
...测试一下删除看板功能正常
下面是删除任务功能
编辑 src\utils\task.ts创建并导出 useDeleteTask
...
export const useDeleteTask (queryKey: QueryKey) {const client useHttp();return useMutation((id?: number) client(tasks/${id}, {method: DELETE,}),useDeleteConfig(queryKey));
};编辑 src\screens\ViewBoard\components\taskModal.tsx
...
import { useDeleteTask, useEditTask } from utils/task;export const TaskModal () {...const { mutateAsync: deleteTask } useDeleteTask(useTasksQueryKey());...const startDelete () {close();Modal.confirm({okText: 确定,cancelText: 取消,title: 确定删除看板吗,onOk() {deleteTask(Number(editingTaskId));}})}return (Modal {...}Form {...}.../Formdiv style{{ textAlign: right }}Button style{{fontSize: 14px}} sizesmall onClick{startDelete}删除/Button/div/Modal);
};测试一下删除任务功能正常 部分引用笔记还在草稿阶段敬请期待。。。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88175.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!