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

如何实现React下拉菜单点击时仅展开当前菜单不全部打开

问题现象

实现React下拉菜单组件时出现异常:点击任意单个主菜单尝试展开对应子菜单时,所有主菜单的子菜单会被同时展开。
原问题实现代码如下:

import React from "react";

export default function App() {
  const [active, setActive] = React.useState(false);
  function handleClick() {
    setActive(!active);
  }

  const text = [
    {
      id: 1,
      name: "Hello",
      subText: [
        {
          id: 1,
          name: "Sub Hello"
        }
      ]
    },
    {
      id: 2,
      name: "Bye",
      subText: [
        {
          id: 2,
          name: "Sub Bye"
        }
      ]
    }
  ];
  return (
    <div style={{ backgroundColor: "gray", padding: 4 }}>
      {text?.map(({ name, id, subText }) => (
        <div style={{ display: "flex", alignItems: "center" }}>
          <ul style={{ width: 100 }}>
            <li style={{ cursor: "pointer" }} onClick={handleClick}>
              {name}
            </li>
          </ul>
          <div>
            {active &&
              subText?.map(({ name, id }) => (
                <ul key={id}>
                  <li>{name}</li>
                </ul>
              ))}
          </div>
        </div>
      ))}
    </div>
  );
}
根因分析
  • 所有菜单项共用同一个布尔类型的active状态,没有区分当前激活的是哪个菜单项
  • 遍历渲染所有菜单项时,只要active值为true,所有菜单项的子菜单判断条件都会命中,因此全部展开
  • 点击事件没有传入当前点击菜单项的唯一标识,无法定位要操作的具体菜单
  • 列表遍历缺失必填的key属性,存在渲染性能和状态错位隐患
修复方案

将布尔状态替换为存储当前激活菜单ID的状态,点击时传入对应菜单ID,渲染子菜单时仅当当前菜单ID与激活ID一致时才展示内容:

import React from "react";

export default function App() {
  // 存储当前激活的菜单id,默认值为null表示无激活菜单
  const [activeId, setActiveId] = React.useState(null);
  // 点击时传入当前菜单id,支持点击已展开菜单时收起
  function handleClick(menuId) {
    setActiveId(prev => prev === menuId ? null : menuId);
  }

  const text = [
    {
      id: 1,
      name: "Hello",
      subText: [
        {
          id: 1,
          name: "Sub Hello"
        }
      ]
    },
    {
      id: 2,
      name: "Bye",
      subText: [
        {
          id: 2,
          name: "Sub Bye"
        }
      ]
    }
  ];
  return (
    <div style={{ backgroundColor: "gray", padding: 4 }}>
      {text?.map(({ name, id, subText }) => (
        <div key={id} style={{ display: "flex", alignItems: "center" }}>
          <ul style={{ width: 100 }}>
            <li 
              style={{ cursor: "pointer" }} 
              onClick={() => handleClick(id)}
            >
              {name}
            </li>
          </ul>
          <div>
            {/* 仅匹配当前激活id的菜单渲染子内容 */}
            {activeId === id &&
              subText?.map(({ name, id: subId }) => (
                <ul key={subId}>
                  <li>{name}</li>
                </ul>
              ))}
          </div>
        </div>
      ))}
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Athief Aleaf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:27:26