“任务”数组在调用某些调度程序时消失(MERN 堆栈)

问题描述 投票:0回答:1

我正在开发一个执行 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;
javascript reactjs node.js mern
1个回答
0
投票

问题出在您的减速器taskReducer中,当您单击编辑并分派EDIT_TASK时,您将状态更新为...您定义为空数组的任务。这就是为什么你的列表变空的原因。

删除它,它会解决你的问题,但是当你在数据更新后得到响应时,你需要找到一种方法来更新状态。

© www.soinside.com 2019 - 2024. All rights reserved.