You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React TodoList筛选异常:新增未完成任务显示在已完成列表

TodoList筛选功能修复方案

核心问题分析

  1. 你错误地将筛选后的任务列表直接替换了全局任务状态,导致筛选状态下新增任务时,任务会被添加到筛选后的列表而非完整任务列表,进而出现不符合筛选条件的任务依然显示的问题。
  2. initilState与reducer维护的tasks状态同步混乱,筛选逻辑依赖冗余状态,导致状态更新不一致。

修复步骤及代码实现

1. 简化状态管理

移除initilState、filterTodo冗余状态,新增filterCondition存储当前筛选选项,让reducer仅负责维护完整的任务列表。

2. 重构筛选逻辑

不再通过reducer修改任务列表实现筛选,而是根据filterCondition从完整任务列表中实时派生需要显示的任务。

3. 修正任务操作逻辑

所有增删改操作直接作用于完整任务列表,筛选仅作为视图层的过滤规则。

修改后的完整代码:

import { useReducer, useState } from "react";
import styles from "./App.module.css";
import Select from "react-select";

function TodoForm() {
    const [inputState, setInputState] = useState("");
    const [selectValue, setSelectValue] = useState("");
    // 存储当前筛选条件
    const [filterCondition, setFilterCondition] = useState("");
    const SelectOptions = [
        { value: "", label: "All" },
        { value: "NotDone", label: "Not Completed" },
        { value: "Done", label: "Completed" }
    ];

    const reducer = (state, action) => {
        switch (action.type) {
            case "InputChange":
                action.event.preventDefault();
                const newTask = { title: inputState, isDone: false, isEditing: false };
                // 直接返回新的完整任务列表
                return [...state, newTask];
            case "CompleteTask":
                return state.map((task, index) => 
                    index === action.id ? { ...task, isDone: !task.isDone } : task
                );
            case "deleteTask":
                return state.filter((_, index) => index !== action.id);
            case "editTask":
                return state.map((task, index) => 
                    index === action.id ? { ...task, isEditing: !task.isEditing } : task
                );
            case "editInput":
                return state.map((task, index) => 
                    index === action.id ? { ...task, title: action.event.target.value } : task
                );
            default:
                return state;
        }
    };

    const [tasks, dispatchTasks] = useReducer(reducer, []);

    const handleSelectChange = (event) => {
        setFilterCondition(event.value);
        setSelectValue(event);
    };

    // 根据筛选条件计算要显示的任务
    const filteredTasks = tasks.filter(task => {
        if (filterCondition === "Done") return task.isDone;
        if (filterCondition === "NotDone") return !task.isDone;
        return true; // 默认显示所有
    });

    const uncompletedTasks = tasks.filter(item => !item.isDone);

    return (
        <div id={styles.tasks}>
            <header>
                {uncompletedTasks.length > 0 && <h2>Uncompleted Tasks {uncompletedTasks.length}</h2>}
                <Select
                    options={SelectOptions}
                    value={selectValue}
                    onChange={handleSelectChange}
                />
            </header>
            <form onSubmit={(e) => dispatchTasks({ type: "InputChange", event: e })}>
                <input 
                    type="text" 
                    value={inputState} 
                    onChange={(e) => setInputState(e.target.value)}
                    placeholder="Enter task"
                />
                <button type="submit">Add</button>
            </form>
            <section>
                <ul>
                    {filteredTasks.map((task, index) => {
                        if (!task.title) return null;
                        return (
                            <li key={index}>
                                {task.isEditing ? (
                                    <input 
                                        type="text" 
                                        className={styles.editInput} 
                                        onChange={(e) => dispatchTasks({ type: "editInput", id: index, event: e })} 
                                        value={task.title}
                                    />
                                ) : (
                                    <span className={`${task.isDone && styles.true}`}>Task Name: {task.title}</span>
                                )}
                                <span>
                                    <span>Is Task Completed:</span> 
                                    <input 
                                        type="checkbox" 
                                        checked={task.isDone} 
                                        onClick={() => dispatchTasks({ type: "CompleteTask", id: index })}
                                    />
                                </span>
                                <button onClick={() => dispatchTasks({ type: "deleteTask", id: index })}>delete</button>
                                <button onClick={() => dispatchTasks({ type: "editTask", id: index })}>
                                    {task.isEditing ? "save" : "edit"}
                                </button>
                            </li>
                        );
                    })}
                </ul>
            </section>
        </div>
    );
}

export default TodoForm;

关键优化点

  • 用filteredTasks实时派生筛选结果,避免修改原始任务列表
  • reducer仅负责维护完整任务数据,职责更清晰
  • 新增任务始终添加到完整列表,筛选条件仅控制视图显示,不会影响数据本身

内容的提问来源于stack exchange,提问作者mohammad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:10:16