React待办事项删除功能失效问题求助及解决过程
Todo应用删除按钮失效问题排查与修复
问题描述
开发待办事项应用时,删除任务的按钮功能无法正常工作。原本预期deleteTodo函数能接收对应任务的todo.id,过滤待办列表完成删除,但实际点击按钮后没有效果。
错误原因分析
- 按钮作用域错误:删除按钮被定义在
todos.map()循环外部,导致点击时deleteTodo获取的是组件状态里的todo(也就是输入框绑定的文本状态),而非循环中当前待办项的id,根本匹配不到要删除的任务。 - 状态更新逻辑不严谨:原
deleteTodo直接依赖当前todos状态做更新,在并发操作场景下容易出现状态不一致的问题,推荐用setState的函数式更新来确保基于最新状态修改。
初始错误代码
import React, { useState } from "react"; import "./App.css"; const App = () => { const [todos, setTodos] = useState([]); const [todo, setTodo] = useState(""); const handleSubmit = (e) => { e.preventDefault(); const newTodo = { id: new Date().getTime(), text: todo.trim(), completed: false, }; if (newTodo.text.length > 0) { setTodos([...todos].concat(newTodo)); setTodo(""); } else { alert("Enter Valid Task"); setTodo(""); } } const deleteTodo = (id) => { let updatedTodos = [...todos].filter((todo) => todo.id !== id); setTodos(updatedTodos); } const button = <button onClick={() => deleteTodo(todo.id)}>Delete</button> return ( <div> <h1>To-do List</h1> <form onSubmit={handleSubmit}> <input type="text" onChange={(e) => setTodo(e.target.value)} placeholder="Add a new task" value={todo} /> <button type="submit">Add Todo</button> </form> {todos.map((todo) => <div>ID: {todo.id} Task: {todo.text} {button}</div>)} </div> ); }; export default App;
修正后的代码
import React from "react"; import "./App.css"; const App = () => { const [todos, setTodos] = React.useState([]); const [todo, setTodo] = React.useState(""); const handleSubmit = (e) => { e.preventDefault(); const newTodo = { id: new Date().getTime(), text: todo.trim(), completed: false, }; if (newTodo.text.length > 0) { setTodos(todos.concat(newTodo)); setTodo(""); } else { alert("Enter a valid task"); setTodo(""); } } // 使用函数式更新状态,确保基于最新状态修改 const deleteTodo = id => { setTodos(prevState => { return prevState.filter(todo => todo.id !== id) }); }; return ( <> <h1>Todo List</h1> <form onSubmit={handleSubmit}> <input type="text" onChange={(e) => setTodo(e.target.value)} placeholder="Add a new task..." value={todo} /> </form> {todos.map((todo) => <div> ID: {todo.id} Task: {todo.text} <button onClick={() => deleteTodo(todo.id)}>Delete</button> </div>)} </> ); }; export default App;
关键修复点
- 把删除按钮移到
todos.map()循环内部,让每个按钮都绑定当前待办项的id,点击时能正确传递要删除任务的标识。 - 重构
deleteTodo函数,改用setTodos的函数式更新形式,通过prevState获取最新的待办列表状态,避免状态不一致问题。
内容的提问来源于stack exchange,提问作者dorraj.
相关产品推荐
相关产品推荐

