React项目中单个下拉菜单独立切换的修复方法
修复React下拉菜单点击联动问题
问题描述
我有一个React项目,包含3个并排的下拉菜单,点击其中一个时所有菜单都会切换展开/收起状态,而非仅切换被点击的菜单,需要修复这个问题让每个下拉菜单独立控制自身显示状态。
问题原因
当前代码使用单个toggle状态变量控制所有下拉菜单的显示/隐藏,所有菜单的展开状态都绑定到同一个变量,因此点击任意一个菜单都会触发所有菜单的状态变化。
解决方案
为每个下拉菜单单独维护状态,用对象记录每个菜单ID对应的展开状态,点击时仅更新当前菜单的状态:
- 将状态初始化为对象,存储各菜单ID的展开状态
- 点击菜单标题时,切换对应ID的状态
- 根据当前菜单ID的状态判断下拉内容是否显示
修复后的代码
import { useState } from 'react'; import { iconHamburger, iconClose, iconArrowDark, iconArrowLight, logo, } from '../assets'; import { navLinks } from '../constants'; const Navbar = () => { // 用对象存储每个菜单的展开状态,key为菜单id,value为布尔值 const [expandedMenus, setExpandedMenus] = useState({}); // 切换指定菜单的展开状态 const toggleMenu = (menuId) => { setExpandedMenus(prev => ({ ...prev, [menuId]: !prev[menuId] })); }; return ( <nav className='w-full flex py-6 ml-10 justify-between items-center navbar'> <img src={logo} alt='blogr' className='w-[75px] h-[30px]' /> <ul className='list-none sm:flex hidden ml-10 justify-start items-center flex-1'> {navLinks.map((nav, index) => ( <li key={nav.id} className={`font-overpass font-normal text-[12px] ${index === navLinks.length - 1 ? 'mr-0' : 'mr-10'} text-white`}> <a className='float-left' onClick={() => toggleMenu(nav.id)} href={`#${nav.id}`}> {nav.title} <img className='ml-2 mt-1 cursor-pointer float-right w-[9px] h-[6px]' src={iconArrowLight} /> </a> {/* 根据当前菜单id的状态判断是否显示下拉 */} <div className={`${expandedMenus[nav.id] ? 'relative' : 'hidden'} mr-10`}> <ul className='list-none mt-10 absolute'> {nav.links.map((link, index) => ( <li key={link.name} className={`font-overpass text-black cursor-pointer ${index !== nav.links.length - 1 ? 'mb-4' : 'mb-0'}`}> {link.name} </li> ))} </ul> </div> </li> ))} </ul> </nav> ); }; export default Navbar;
可选优化:点击其他菜单自动关闭当前展开项
如果需要实现点击新菜单时自动关闭已展开的菜单,可修改toggleMenu函数:
const toggleMenu = (menuId) => { setExpandedMenus(prev => { // 当前菜单已展开则关闭;否则关闭所有其他菜单,仅展开当前 if (prev[menuId]) { return { ...prev, [menuId]: false }; } else { const newState = {}; Object.keys(prev).forEach(id => newState[id] = false); newState[menuId] = true; return newState; } }); };
内容的提问来源于stack exchange,提问作者rachel
相关产品推荐
相关产品推荐

