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

ReactJS开发手风琴菜单如何实现展开一项时自动关闭其余项

核心问题分析

你目前的实现中每个ListItem都独立维护自身的展开状态,组件间状态互不可见,因此无法实现展开一个时自动关闭其他项的效果。我们需要把展开状态提升到公共父组件Menu2中统一管理即可解决。


调整后的完整代码

原有CSS不需要改动:

.accordion-cnt { display: none; }
.accordion-cnt.on { display: block; }

JSX代码调整如下:

// 子组件不再维护独立状态,通过props接收控制参数
const ListItem = (props) => {
  const { id, isActive, onToggle } = props;
  return (
    <li className={`accordion-item ${isActive ? "on" : ""}`}>
      <button onClick={() => onToggle(id)}>
        title
      </button>
      <div className={`accordion-cnt ${isActive ? "on" : ""}`}>
        content
      </div>
    </li>
  );
};  

const Menu2 = () => {
  // 父组件存储当前激活的菜单项id,null代表所有项都关闭
  const [activeId, setActiveId] = React.useState(null);

  const handleToggle = (currentId) => {
    // 如果点击的是已经激活的项就关闭,否则切换为当前点击的项
    setActiveId(activeId === currentId ? null : currentId);
    // 如果不需要点击已展开项可关闭的效果,直接写成 setActiveId(currentId) 即可
  };

  return (
    <>  
      <ul className="accordion-list"> 
        <ListItem id={1} isActive={activeId === 1} onToggle={handleToggle} />
        <ListItem id={2} isActive={activeId === 2} onToggle={handleToggle} />
        <!-- 后续新增菜单项只要按规则传id参数即可 -->
      </ul> 
    </>
  );
};

逻辑说明

父组件统一存储当前激活项的唯一ID,每次点击某个菜单项时,只会把激活ID更新为当前点击项的ID,其余所有项的激活状态判断都会为false,自动关闭,自然就实现了互斥展开的效果。如果需要扩展更多菜单项,只要给每个ListItem传入唯一的id参数即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:45:02