You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React实现列表悬停时仅显示当前元素隐藏其余元素的方法

问题描述
  1. 需要在React列表中实现:当鼠标悬停在某一元素上时,隐藏列表中其他所有元素。
  2. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 15:45:30