如何在Next.js中使用useState Hook实现多个下拉菜单独立控制
问题根源
你当前所有侧边栏菜单项共用同一个布尔类型的isActive状态,任意菜单点击触发的状态修改都会作用到所有绑定了这个状态的菜单上,所以会出现点击一个所有同级菜单都同步切换显隐的问题。
解决方案1:用唯一标识存储激活状态(适合菜单数量较多的场景)
将状态值从布尔值改为当前激活菜单的唯一标识(比如菜单名称、自定义ID),切换时只有匹配标识的菜单才会触发显隐:
- 状态与切换逻辑修改:
// 初始值为空,代表没有展开的菜单 const [activeMenu, setActiveMenu] = useState(''); const handleToggle = (menuKey) => { // 如果点击的是当前展开的菜单,就收起,否则展开对应菜单 setActiveMenu(activeMenu === menuKey ? '' : menuKey); }
- 菜单渲染逻辑修改:
给每个菜单传入唯一标识,这里Clients菜单可以用clients作为key:
<li> <a className={`${activeMenu === 'clients' ? 'open-sibling' : 'hidden-sibling'} left-menu-list`} onClick={() => handleToggle('clients')} > <i className="las la-user-alt mr-2"></i> <span>Clients</span> <i className="las la-angle-up ml-auto"></i> </a> <ul> <Link href="/clients/list"> <li> <a className="left-menu-list"> <i className="las la-users mr-2"></i> View All Clients </a> </li> </Link> </ul> </li>
其他同级菜单只要传入各自的唯一key(比如products/orders)即可实现独立控制。
解决方案2:抽离独立下拉菜单组件(更符合组件化封装思想)
把单个下拉菜单抽成独立组件,内部自己维护展开状态,每个组件的状态完全隔离,不会互相影响:
- 封装独立组件:
import { useState } from 'react'; const SidebarDropdown = ({ menuName, icon, children }) => { const [isActive, setIsActive] = useState(false); const handleToggle = () => setIsActive(!isActive); return ( <li> <a className={`${isActive ? 'open-sibling' : 'hidden-sibling'} left-menu-list`} onClick={handleToggle} > <i className={`las ${icon} mr-2`}></i> <span>{menuName}</span> <i className="las la-angle-up ml-auto"></i> </a> <ul>{children}</ul> </li> ) }
- 父组件中调用:
<SidebarDropdown menuName="Clients" icon="la-user-alt"> <Link href="/clients/list"> <li> <a className="left-menu-list"> <i className="las la-users mr-2"></i> View All Clients </a> </li> </Link> </SidebarDropdown> {/* 其他同级菜单直接复用组件即可 */} <SidebarDropdown menuName="Products" icon="la-box"> {/* 产品菜单子项 */} </SidebarDropdown>
内容的提问来源于stack exchange,提问作者Himanshu Jain
相关产品推荐
相关产品推荐

