React中点击单个Dropdown组件却全部展开的问题求助
问题分析
你遇到的问题核心在于:如果是希望同一时间仅展开一个下拉菜单,当前代码中每个Dropdown组件独立维护自己的isActive状态,无法实现互斥展开;如果是点击单个菜单却触发三个同时展开,大概率是CSS布局导致下拉层重叠,看起来像同时展开(从你提供的代码看,子组件独立状态本身不会触发这个问题)。
解决方案
根据你的需求,分两种场景给出实现:
场景1:允许同时展开多个下拉菜单
如果希望多个菜单可以同时展开,当前代码逻辑是正确的,只需调整CSS避免下拉层重叠:
- 给
Dropdown的容器添加position: relative - 给下拉列表添加
position: absolute,确保每个下拉层相对于自身父元素定位
修改后的Dropdown组件:
const Dropdown = ({name, selected, setSelected, options}) => { const [isActive, setIsActive] = useState(false); return ( <div className='bg-white cursor-pointer w-[100px] relative'> <div className='flex justify-between items-center p-2' onClick={() => setIsActive(!isActive)}> {name} <span><AiOutlineArrowDown /></span> </div> { isActive && ( <div className='absolute top-full left-0 right-0 bg-white border-t'> {options.map((option, index) => ( <div key={index} onClick={() => { setSelected(option); setIsActive(false) }} className='p-2 hover:bg-gray-100' > {option} </div> ))} </div> ) } </div> ) } export default Dropdown
场景2:同一时间仅展开一个下拉菜单
如果希望点击一个菜单时自动收起其他菜单,需要由父组件Navbar统一控制展开状态:
修改Navbar组件
const Navbar = () => { // 存储每个菜单的选中值,避免共享状态导致选中项同步变化 const [selected, setSelected] = useState({ Jobs: null, Talent: null, Reports: null }); // 存储当前展开的菜单名称,实现互斥展开 const [expandedMenu, setExpandedMenu] = useState(null); // 切换菜单展开状态 const toggleMenu = (menuName) => { setExpandedMenu(expandedMenu === menuName ? null : menuName); }; // 更新对应菜单的选中值 const updateSelected = (menuName, option) => { setSelected(prev => ({...prev, [menuName]: option})); toggleMenu(menuName); // 选中后自动收起菜单 }; return ( <div className='flex justify-evenly items-center h-[80px] bg-black'> <div className='logo_container'> <img src={logo} alt='' /> </div> <div className='flex w-fit gap-2'> <Dropdown name={'Jobs'} selected={selected.Jobs} onSelect={(option) => updateSelected('Jobs', option)} options={['My Jobs', 'All Job Posts', 'All Contracts', 'Post Job']} isActive={expandedMenu === 'Jobs'} onToggle={() => toggleMenu('Jobs')} /> <Dropdown name={'Talent'} selected={selected.Talent} onSelect={(option) => updateSelected('Talent', option)} options={['My Jobs', 'All Job Posts', 'All Contracts', 'Post Job']} isActive={expandedMenu === 'Talent'} onToggle={() => toggleMenu('Talent')} /> <Dropdown name={'Reports'} selected={selected.Reports} onSelect={(option) => updateSelected('Reports', option)} options={['My Jobs', 'All Job Posts', 'All Contracts', 'Post Job']} isActive={expandedMenu === 'Reports'} onToggle={() => toggleMenu('Reports')} /> </div> </div> ) } export default Navbar
修改Dropdown组件
const Dropdown = ({name, selected, onSelect, options, isActive, onToggle}) => { return ( <div className='bg-white cursor-pointer w-[100px] relative'> <div className='flex justify-between items-center p-2' onClick={onToggle}> {name} <span><AiOutlineArrowDown /></span> </div> { isActive && ( <div className='absolute top-full left-0 right-0 bg-white border-t'> {options.map((option, index) => ( <div key={index} onClick={() => onSelect(option)} className='p-2 hover:bg-gray-100' > {option} </div> ))} </div> ) } </div> ) } export default Dropdown
额外优化点
- 给
options.map的子元素添加key属性,避免React警告 - 将共享的
selected状态改为对象,确保每个菜单的选中值独立,不会互相影响
内容的提问来源于stack exchange,提问作者Daniyal Sohail
相关产品推荐
相关产品推荐

