React TodoList筛选异常:新增未完成任务显示在已完成列表
TodoList筛选功能修复方案
核心问题分析
- 你错误地将筛选后的任务列表直接替换了全局任务状态,导致筛选状态下新增任务时,任务会被添加到筛选后的列表而非完整任务列表,进而出现不符合筛选条件的任务依然显示的问题。
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
相关产品推荐
相关产品推荐

