React实现列表悬停时仅显示当前元素隐藏其余元素的方法
问题描述
- 需要在React列表中实现:当鼠标悬停在某一元素上时,隐藏列表中其他所有元素。
- 在ToDo组件中实现:当某个ToDo组件被悬停时,隐藏其他ToDo组件的删除按钮,仅保留当前悬停组件的删除按钮可见。
用户提供的ToDo组件代码如下:
// ToDo Component import React from "react"; export default function ToDo({ item, deleteTask, taskCompleteStatus, }) { return ( <div className="ToDo"> {/* ToDo Form */} <form className="ToDo__form"> {/* Label */} <label className="ToDo__form__label" htmlFor={`todo-${item.id}`}> <div className={ item.complete ? "ToDo__form__label__task complete" : "ToDo__form__label__task" } > <p>{item.task}</p> </div> {/* Checkbox*/} <div className="ToDo__form__label__checkbox"> <input type="checkbox" id={`todo-${item.id}`} name="complete" checked={item.complete} onChange={() => taskCompleteStatus(item.id)} /> <span></span> </div> </label> {/* Delete Button - delete task when clicked*/} {/* 需要实现:当某一ToDo被悬停时,隐藏其他ToDo的这个按钮,仅保留当前悬停的显示 */} <button type="button" id={item.id} className="ToDo__form__delete-btn" onClick={deleteTask} > <span className="span__1"></span> <span className="span__2"></span> </button> </form> </div> ); }
解决方案
核心思路是在父组件中统一管理当前悬停的任务ID,然后将这个状态传递给所有子ToDo组件,子组件根据该状态判断自身是否隐藏、删除按钮是否显示。
步骤1:父组件添加悬停状态管理
假设渲染ToDo列表的父组件为ToDoList,添加状态跟踪当前悬停的任务ID:
import React, { useState } from "react"; import ToDo from "./ToDo"; export default function ToDoList({ tasks, deleteTask, taskCompleteStatus }) { // 保存当前悬停的任务ID,初始为null表示无元素被悬停 const [hoveredTaskId, setHoveredTaskId] = useState(null); return ( <div className="ToDoList"> {tasks.map(task => ( <ToDo key={task.id} item={task} deleteTask={() => deleteTask(task.id)} taskCompleteStatus={taskCompleteStatus} hoveredTaskId={hoveredTaskId} // 传递悬停事件处理函数 onMouseEnter={() => setHoveredTaskId(task.id)} onMouseLeave={() => setHoveredTaskId(null)} /> ))} </div> ); }
步骤2:修改ToDo组件,根据状态控制显示
更新ToDo组件,接收悬停相关属性,分别处理两个需求:
- 隐藏其他元素:当
hoveredTaskId不为null且不等于当前item.id时,给容器添加隐藏类; - 控制删除按钮显示:仅当无悬停状态,或当前元素是被悬停元素时,渲染删除按钮。
修改后的ToDo组件:
import React from "react"; export default function ToDo({ item, deleteTask, taskCompleteStatus, hoveredTaskId, onMouseEnter, onMouseLeave, }) { // 判断当前组件是否需要隐藏(对应第一个需求) const isHidden = hoveredTaskId !== null && hoveredTaskId !== item.id; // 判断删除按钮是否需要显示(对应第二个需求) const showDeleteBtn = hoveredTaskId === null || hoveredTaskId === item.id; return ( <div className={`ToDo ${isHidden ? "hidden" : ""}`} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} > {/* ToDo Form */} <form className="ToDo__form"> {/* Label */} <label className="ToDo__form__label" htmlFor={`todo-${item.id}`}> <div className={ item.complete ? "ToDo__form__label__task complete" : "ToDo__form__label__task" } > <p>{item.task}</p> </div> {/* Checkbox*/} <div className="ToDo__form__label__checkbox"> <input type="checkbox" id={`todo-${item.id}`} name="complete" checked={item.complete} onChange={() => taskCompleteStatus(item.id)} /> <span></span> </div> </label> {/* 仅符合条件时渲染删除按钮 */} {showDeleteBtn && ( <button type="button" id={item.id} className="ToDo__form__delete-btn" onClick={deleteTask} > <span className="span__1"></span> <span className="span__2"></span> </button> )} </form> </div> ); }
步骤3:添加CSS样式(可选)
为隐藏/显示效果添加过渡动画,提升体验:
.ToDo { transition: all 0.2s ease; margin: 8px 0; } .ToDo.hidden { opacity: 0; visibility: hidden; height: 0; margin: 0; padding: 0; overflow: hidden; }
补充说明
- 如果只需要实现删除按钮的显示控制,可以忽略
isHidden相关逻辑,仅保留showDeleteBtn的判断即可; - 这种通过父组件统一管理状态的方式,无需循环单独处理每个元素,所有子组件自动同步状态,逻辑更简洁。
内容的提问来源于stack exchange,提问作者rigan
相关产品推荐
相关产品推荐

