React点击删除数组元素仅顶部生效、Filter方法无效果问题求助
问题原因
你的代码存在3处核心错误导致删除功能异常:
Array.map参数命名混淆:map的第一个参数为当前遍历的元素对象,第二个才是索引值,你代码中todos.map((key, value) =>)的命名完全颠倒,导致后续传参错误- 删除逻辑入参不匹配:点击删除按钮时你给
deleteTodo传递的是完整的todo对象,而非id或索引:- 采用filter方案时,你用数字id和todo对象做全等判断,永远返回true,所以不会过滤任何元素,数组长度无变化
- 采用splice方案时,splice接收到todo对象后会尝试转数字,得到的结果为NaN,splice默认将无效下标当做0处理,因此永远删除数组第一个元素
- 状态日志逻辑错误:React的
setTodos是异步更新,你在调用后直接打印todos.length拿到的是更新前的旧值,不能作为删除是否生效的判断依据
修复方案(推荐基于ID删除,稳定性更高)
import { useEffect, useState } from "react"; const Task = () => { const [todos, setTodos] = useState([]); useEffect(() => { fetch('http://jsonplaceholder.typicode.com/todos') .then(res => res.json()) .then(data => { setTodos(data) }) }, []); // 基于ID删除 const deleteTodo = (id) => { const newTodo = todos.filter(todo => todo.id !== id); setTodos(newTodo); // 要查看更新后长度请在setTodos的回调或者useEffect中监听todos变化 } return ( <div className='container'> <table className='table'> <tbody> {/* 修正map参数命名 */} {todos.map((todo, index) => ( <tr key={todo.id}> <td>{todo.id}</td> <td>{todo.title}</td> <td>{`${todo.completed}`}</td> <td> {/* 传递当前todo的id到删除函数 */} <button className='btn btn-danger ' onClick={() => deleteTodo(todo.id)}> Delete </button> </td> </tr> ))} </tbody> </table> <button className='btn btn-primary'>Add Task</button> </div> ); } export default Task;
如果你要使用索引删除的方案可参考如下修改
// 基于索引删除的函数 const deleteTodo = (index) => { const temp = [...todos]; temp.splice(index, 1); setTodos(temp); } // 调用处传索引即可 <button className='btn btn-danger ' onClick={() => deleteTodo(index)}> Delete </button>
内容的提问来源于stack exchange,提问作者coolhack7
相关产品推荐
相关产品推荐

