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

React中点击其他子菜单时自动关闭已展开子菜单的实现问题

实现菜单互斥展开的解决方案

你当前的实现中每个MenuItem独立维护自身的展开状态,组件之间没有状态同步,所以无法实现点击一个菜单自动关闭其他已展开菜单的效果。我们可以通过状态提升的方式,把展开状态统一放到父组件Menu中管理,具体修改如下:


1. 修改Menu.js代码

将展开状态的控制权移到父组件,统一管理当前激活的展开项:

import React, { useState } from 'react'
import MenuItem from '../MenuItem';
import { SidebarData } from '../../helpers/SidebarData';
import * as C from './styles';

const Menu = () => {
    // 存储当前展开的菜单项唯一标识,默认无展开项设为null
    const [activeMenuId, setActiveMenuId] = useState(null);

    const handleMenuToggle = (menuId) => {
        // 点击已展开的菜单则关闭,否则切换为当前点击的菜单
        setActiveMenuId(activeMenuId === menuId ? null : menuId)
    }

    return (
        <C.Container>
            <C.MenuArea>
                {SidebarData.map((item, index) => {
                    // 若SidebarData的项有唯一id优先用item.id,无则先用index作为临时标识
                    const menuId = item.id || index;
                    return <MenuItem 
                        item={item} 
                        key={menuId} 
                        isOpened={activeMenuId === menuId}
                        onToggle={() => handleMenuToggle(menuId)}
                    />;
                })}
            </C.MenuArea>
        </C.Container>
    )
};

export default Menu

2. 修改MenuItem.js代码

移除内部的独立展开状态,改用父组件传入的状态和回调:

import React from 'react';
import { NavLink } from 'react-router-dom';
import * as C from './styles';

const MenuItem = ({ item, isOpened, onToggle }) => {
    return (
        <C.NavUnlisted>
            <NavLink 
                to={item.path} 
                onClick={item.subNav ? onToggle : undefined} 
                activeClassName='current' 
                exact={item.path === '/'} 
            >
                <C.SidebarLink>
                    <div>
                        {item.icon}
                        <C.SidebarLabel>{item.title}</C.SidebarLabel>
                    </div>
                    <div>
                        {item.subNav && isOpened
                            ? item.iconOpened
                            : item.subNav
                                ? item.iconClosed
                                : null}
                    </div>
                </C.SidebarLink>
            </NavLink>
            {isOpened &&
                item.subNav.map((subItem, index) => {
                    return (
                        <NavLink to={subItem.path} key={index} activeClassName='current' >
                            <C.DropdownLink>
                                {subItem.icon}
                                <C.SidebarLabel>{subItem.title}</C.SidebarLabel>
                            </C.DropdownLink>
                        </NavLink>
                    );
                })}
        </C.NavUnlisted>
    );
};

export default MenuItem;

提示:如果你的SidebarData配置项中已经存在唯一标识字段(比如id),建议替换掉示例中用index作为menuId的写法,避免数组顺序变化导致的状态异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 03:54:04