我正在开发一个执行 CRUD 操作的 MERN 堆栈“待办事项列表”应用程序。屏幕的一侧有任务列表,另一侧有表单用于添加新任务或编辑现有任务。
为了从列表中编辑“任务”,我单击每个任务旁边可见的“编辑”按钮,任务标题和描述将通过表单获取。然后我编辑这些内容并将其保存回数据库。功能上没有问题。
但是,在单击“编辑”按钮后,我的任务列表完全消失,并显示“未找到任务”,并且直到刷新页面才返回。这仅在我编辑现有任务时发生。当我添加新任务时,我的任务列表保留在那里,甚至新任务也会动态添加到列表底部。
这是一个前端问题,目前我还无法修复。我用
console.log
确认任务在 UI 上变得不可见,但实际上仍然存在并且运行没有问题。我的控制台上也没有错误日志。 我注意到的是:为了获取现有任务,我创建了两个调度程序case 'SET_EDIT_MODE':
来开始编辑,以及case "CLEAR_EDIT_MODE":
在单击“保存”后结束编辑。调用这两个调度程序后,我的任务数组消失了。
我正在分享相关的代码片段,希望有人能给我一点帮助。我们将不胜感激您的时间和精力。
taskReducer.js
文件:
function taskReducer(tasks = [], action) {
console.log("taskreducer");
switch (action.type) {
// eslint-disable-next-line no-lone-blocks
case "ADD_TASK": {
return [
...tasks,
{
_id: action._id,
title: action.title,
description: action.description,
completed: false
}
]
}
case "SET_TASK": {
return action.payload
}
case "REMOVE_TASK": {
console.log("Tasks before removal:", tasks);
const updatedTasks = tasks.filter((task) => task._id !== action._id);
console.log("Tasks after removal:", updatedTasks);
return updatedTasks;
}
case "MARK_DONE": {
return tasks.map((task) => {
if (task._id === action._id) {
return {
...task,
completed: !task.completed
}
}
return task
})
}
case "EDIT_TASK": {
const { taskToEdit, title, description } = action;
// Ensure taskToEdit exists within tasks object
if (tasks && tasks.taskToEdit) {
const updatedTask = {
...tasks.taskToEdit,
title,
description
};
// Return a new object maintaining the original structure
return {
...tasks,
taskToEdit: {
...tasks.taskToEdit,
title,
description
},
[taskToEdit]: updatedTask // Update the specific task in the tasks object
};
}
return tasks; // Return original state if tasks or taskToEdit is missing
}
case 'SET_EDIT_MODE': {
console.log('Processing SET_EDIT_MODE:', action.payload);
return {
...tasks,
taskToEdit: action.payload, // Set the task for editing
editMode: true // Set edit mode to true
};
}
case "CLEAR_EDIT_MODE": {
console.log('Processing CLEAR_EDIT_MODE');
return {
...tasks,
taskToEdit: null,
editMode: false
};
}
default: {
throw Error("Unknown Action" + action.type)
}
}
}
export default taskReducer;
Task.jsx
组件:
import React, { useContext } from 'react';
import moment from 'moment';
import "../styles/task.css";
import axios from "../axios/axios.js"
import TaskContext from '../context/TaskContext.js';
import TokenContext from '../context/TokenContext.js';
import DeleteIcon from '@mui/icons-material/Delete';
import EditIcon from '@mui/icons-material/Edit';
function Task({ task }) {
const { _id, title, description, completed } = task;
const { dispatch } = useContext(TaskContext);
const { userToken } = useContext(TokenContext);
... // Unrelated app logic
// Called clicking on Edit button
const handleEdit = () => {
console.log('Editing task:', { task }); // Log the task details being edited
// Dispatch an action to set the task for editing
console.log('Dispatching SET_EDIT_MODE with task:', task);
dispatch({
type: 'SET_EDIT_MODE',
payload: task // Send the entire task object for editing
});
};
... // Unrelated UI code
export default Task;
SaveTask.jsx
组件:
import React, { useState, useEffect, useContext } from 'react';
import TaskContext from '../context/TaskContext';
import TokenContext from '../context/TokenContext';
import axios from "../axios/axios";
import "../styles/saveTask.css";
function SaveTask() {
const { tasks, dispatch } = useContext(TaskContext);
const { userToken } = useContext(TokenContext);
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const { editMode, taskToEdit } = tasks; // Extract editMode and taskToEdit from context
useEffect(() => {
// Populate form fields with task details when in editMode
if (editMode && taskToEdit) {
setTitle(taskToEdit.title);
setDescription(taskToEdit.description);
} else {
setTitle(""); // Reset title when not editing
setDescription(""); // Reset description when not editing
}
}, [editMode, taskToEdit]);
// Form logic
const handleAddOrEdit = async (e) => {
e.preventDefault();
try {
if (editMode && taskToEdit) {
// Update existing task
const res = await axios.post(`/task/editTask/${taskToEdit._id}`, { title, description }, {
headers: {
Authorization: `Bearer ${userToken}`
}
});
console.log("Task edited:", res.data);
// Update task in context
dispatch({
type: 'EDIT_TASK',
_id: taskToEdit._id,
title: res.data.task.title,
description: res.data.task.description
});
dispatch({ type: 'CLEAR_EDIT_MODE' }); // Clear edit mode after submission
} else {
// Add new task
const res = await axios.post("/task/addTask", { title, description }, {
headers: {
Authorization: `Bearer ${userToken}`
}
});
console.log("New task added:", res.data);
// Add new task to context
dispatch({
type: "ADD_TASK",
_id: res.data.task._id,
title: res.data.task.title,
description: res.data.task.description,
});
}
// Reset form fields
setTitle("");
setDescription("");
} catch (error) {
console.log(error);
}
};
... // Form input fields
export default SaveTask;
AllTask.jsx
组件:
import React, { useContext } from 'react';
import Task from './Task';
import TaskContext from '../context/TaskContext';
function AllTask() {
const { tasks, editMode, taskToEdit } = useContext(TaskContext);
console.log('Tasks:', tasks);
console.log('EditMode:', editMode);
console.log('TaskToEdit:', taskToEdit);
// Tasks list
return (
<div>
{Array.isArray(tasks) && tasks.length !== 0 ? (
tasks.map((task, index) => (
<Task key={index} task={task} id={index} />
))
) : (
<h1>No Tasks Found</h1>
)}
</div>
);
}
export default AllTask;
问题出在您的减速器taskReducer中,当您单击编辑并分派EDIT_TASK时,您将状态更新为...您定义为空数组的任务。这就是为什么你的列表变空的原因。
删除它,它会解决你的问题,但是当你在数据更新后得到响应时,你需要找到一种方法来更新状态。