React待办列表li与嵌套删除按钮onClick事件冲突导致样式错误如何解决
问题根因
你的异常是两个问题叠加导致的:
- 事件冒泡:删除按钮嵌套在
<li>内部,点击按钮的事件会向上冒泡触发父级<li>的点击事件,在删除逻辑执行后,当前ListItem组件的clickedOn状态会被误修改 - 用数组索引作为
key:删除条目后数组索引发生偏移,React会复用索引匹配的旧ListItem组件,导致旧组件的clickedOn状态被误用到新的相邻条目上
最优修正方案
步骤1:阻止删除按钮的事件冒泡
在ListItem的删除按钮点击回调中调用event.stopPropagation(),阻断事件向上传递,避免触发父级<li>的点击事件。
步骤2:替换索引key为唯一标识
调整待办项的数据结构,为每个待办项生成唯一ID,用ID作为ListItem的key,避免组件状态错用。
修改后代码
App.js
import React, { useState } from "react"; import ListItem from "./ListItem"; function App() { const [inputText, setInputText] = useState(""); const [items, setItems] = useState([]); function handleChange(event) { const newValue = event.target.value; setInputText(newValue); } function addItem() { setItems((prevItems) => { // 每个待办项存为带唯一id的对象,用时间戳做简单唯一标识 return [...prevItems, { id: Date.now(), content: inputText }]; }); setInputText(""); } function deleteItem(id) { setItems((prevItems) => { // 按id过滤删除项,不再用索引 return prevItems.filter((item) => item.id !== id); }); } return ( <div className="container"> <div className="heading"> <h1>To-Do List</h1> </div> <div className="form"> <input onChange={handleChange} type="text" value={inputText} /> <button onClick={addItem}> <span>Add</span> </button> </div> <div> <ul> {items.map((todoItem) => ( <ListItem key={todoItem.id} id={todoItem.id} item={todoItem.content} delete={deleteItem} /> ))} </ul> </div> </div> ); } export default App;
ListItem.js
import React, { useState } from "react"; function ListItem(props) { const [clickedOn, setClickedOn] = useState(false); function handleClick() { setClickedOn((prevValue) => !prevValue); } return ( <div> <li onClick={handleClick} style={{ textDecoration: clickedOn ? "line-through" : "none" }} > {props.item} <button onClick={(e) => { // 阻止事件冒泡 e.stopPropagation(); props.delete(props.id); }} style={{ float: "right" }} > <span>Del</span> </button> </li> </div> ); } export default ListItem;
内容的提问来源于stack exchange,提问作者tpdovu
相关产品推荐
相关产品推荐

