React实现点击Show Subtasks仅显示当前任务及子任务的方法
实现方法
你现有代码仅控制了子任务的显隐,没有对顶层任务做过滤,调整状态判断和渲染逻辑就能实现需求,核心改动点如下:
- 统一状态规则:用已有的
open状态存当前聚焦的任务标识(优先用任务id,避免重名冲突,现有代码用task.name也能跑通),约定open为null时是默认全展示状态,open匹配到某任务时仅展示该任务和它的子任务 - 顶层任务加过滤:遍历
todos渲染前先判断状态,聚焦状态下只保留匹配open值的任务,其余任务直接不渲染 - 按钮逻辑对齐:点「Show Subtasks」时把
open设为当前任务的标识,点「Hide Subtasks」时把open重置为null回到全展示状态
代码调整示例
首先确认状态和点击方法的定义:
// open初始值设为null,代表默认展示所有任务 const [open, setOpen] = useState(null); const openClick = (taskIdentifier) => { setOpen(taskIdentifier); }; const closeClick = () => { setOpen(null); };
修改渲染部分的逻辑,核心是给todos遍历增加过滤规则,同时优化按钮显隐、修复原代码的小bug:
return ( <ListGroup> {todos // 新增过滤:聚焦状态下仅返回匹配的当前任务,全展示状态返回所有任务 .filter(task => open === null ? true : task.name === open) .map((task, index) => ( <ListGroup key={task.id || index} > <ListGroupItem style={{ textDecoration: completeTask(task) ? 'line-through' : 'none'}} > {index + 1}....{task.name}....( {task.subdata.length} subtasks ) {/* 非聚焦状态下才显示展开按钮 */} {open !== task.name && ( <Button size='sm' className='mx-2' variant='outline-dark' onClick={() => openClick(task.name)}> Show Subtasks </Button> )} {/* 聚焦状态下才显示收起按钮 */} {open === task.name && ( <Button size='sm' variant='outline-secondary' onClick={closeClick}> Hide Subtasks </Button> )} </ListGroupItem> {task.subdata.filter(child => child.complete === false).map((child, idx) => ( <ListGroupItem style={{ textDecoration: child.complete ? 'line-through' : '', display: open === task.name ? 'block' : 'none' }} key={child.id || idx} className='mx-1' > {child.name} {/* 修复原代码未传入父任务标识的问题 */} <Button size='sm' className='mx-5' variant='outline-dark' onClick={() => handleToggle(child.id, task.name)}> <BsCheckLg /> </Button> </ListGroupItem> ))} <ListGroupItem style={{ fontWeight: 'bold', display: open === task.name ? 'block' : 'none' }} className='mx-2'> Completed Subtasks </ListGroupItem> {task.subdata.filter(child => child.complete === true).map((child, idx) => ( <ListGroupItem style={{ textDecoration: child.complete ? 'line-through' : '', display: open === task.name ? 'block' : 'none' }} key={child.id || idx} className='mx-2' > {child.name} {/* 修复原代码未传入父任务标识的问题 */} <Button size='sm' className='mx-5' variant='outline-dark' onClick={() => unHandleToggle(child.id, task.name)}> <BsXLg /> </Button> </ListGroupItem> ))} </ListGroup> ))} </ListGroup> )
额外优化说明:
- 按钮做了条件渲染,避免两种操作按钮同时占位,交互更符合直觉
- 所有列表项key优先使用数据自带id,替代数组索引,避免React渲染diff时出现状态错乱
- 修复了原代码中子任务操作按钮未传入父任务标识的隐性bug,避免点击时报错
内容的提问来源于stack exchange,提问作者ismbyc
相关产品推荐
相关产品推荐

