React中Todo列表条件样式失效:任务删除线无法正常应用
问题分析与解决方案
你的代码有两个核心问题导致删除线样式不生效:
- 单个状态共享所有任务:你用一个
done变量控制所有任务的完成状态,点击任意按钮都会改变所有任务的样式,这不符合Todo列表“每个任务独立控制状态”的需求。 - 事件冒泡导致状态被覆盖:点击绿色按钮时,先触发按钮的
setDone(true),但事件会冒泡到父元素<li>,触发setDone(false),最终状态还是false,删除线自然不会显示。
修改后的代码
import React, { useState } from 'react'; import "./Tasks.css"; import DoneIcon from '@mui/icons-material/Done'; import CloseIcon from '@mui/icons-material/Close'; function Tasks(props) { // 用Set存储已完成任务的ID,支持快速增删和查找 const [completedTaskIds, setCompletedTaskIds] = useState(new Set()); // 标记任务为完成 const markAsDone = (e, taskId) => { e.stopPropagation(); // 阻止事件冒泡到li元素 setCompletedTaskIds(prev => { const newSet = new Set(prev); newSet.add(taskId); return newSet; }); }; // 取消任务的完成状态 const unmarkAsDone = (taskId) => { setCompletedTaskIds(prev => { const newSet = new Set(prev); newSet.delete(taskId); return newSet; }); }; // 删除任务(补充你缺失的删除逻辑,可根据需求调整) const deleteTask = (e, taskId) => { e.stopPropagation(); props.onDelete?.(taskId); // 依赖父组件处理数据删除,无需求可移除 }; return ( <div className="tasks"> {props.items.map(item => ( <li key={item.id} onClick={() => unmarkAsDone(item.id)} // 精准判断当前任务是否完成,控制删除线显示 style={{textDecorationLine: completedTaskIds.has(item.id) ? 'line-through' : 'none'}} > {item.text} <div> <button onClick={(e) => markAsDone(e, item.id)} style={{color: "green"}} > <DoneIcon/> </button> <button onClick={(e) => deleteTask(e, item.id)} style={{color: "red"}} > <CloseIcon/> </button> </div> </li> ))} </div> ) } export default Tasks;
关键修改说明:
- 独立控制任务状态:用
Set存储已完成任务的ID,每个任务的完成状态互不干扰,点击单个按钮只会改变对应任务的样式。 - 阻止事件冒泡:在按钮点击事件中调用
e.stopPropagation(),避免点击按钮时触发<li>的点击事件,防止状态被意外覆盖。 - 清晰的样式逻辑:用三元表达式明确判断任务是否完成,替代模糊的
done && 'line-through',避免初始null值带来的潜在问题。 - 补全删除逻辑:给红色按钮添加了删除功能,依赖父组件传递
onDelete方法处理数据删除,不需要可直接移除相关代码。
内容的提问来源于stack exchange,提问作者ishika
相关产品推荐
相关产品推荐

