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

如何控制map渲染的单个Dropdown下拉菜单开关及解决样式不生效问题

问题修复方案

存在的问题

  • 传递给DropdownContent的isOpen值错误:当前传入的是整个isOpen状态对象,而非对应id的布尔值,对象在布尔判断中恒为真,导致样式逻辑完全不符合预期
  • 状态更新逻辑错误:修改id为1/2的状态时,没有保留其他id的状态值,会导致其他下拉菜单的状态丢失
  • 显示逻辑写反:DropdownContent的样式中isOpen为true时设为none,和预期的「打开时展示」完全相反
  • 状态处理逻辑扩展性差:写死判断id为1/2、硬编码3/4的状态,后续新增下拉菜单需要反复修改逻辑

修复后的代码

渲染逻辑

{/* 给map渲染的节点加唯一key,避免React渲染警告 */}
{navItems.map(({ id, icon, text}) => (
    <Dropdown key={id}>
        <DropdownButton id={id} onClick={() => handleIsOpen(id)}>
            {text}{icon ? <img src={icon} alt="arrow-down" /> : null}
        </DropdownButton>
        {/* 传入对应id的状态值,而非整个状态对象 */}
        <DropdownContent isOpen={isOpen[id]}>
            <DropdownLink href="#">Link 1</DropdownLink>
            <DropdownLink href="#">Link 2</DropdownLink>
            <DropdownLink href="#">Link 3</DropdownLink>
        </DropdownContent>
    </Dropdown>
))}

状态处理逻辑

// 支持动态根据navItems生成初始状态,无需手动写死id
const [isOpen, setIsOpen] = useState(
  navItems.reduce((acc, item) => {
    acc[item.id] = false
    return acc
  }, {})
);

const handleIsOpen = (id) => {
  // 基于上一次的状态更新,保留所有未点击菜单的状态
  setIsOpen(prevState => ({
    ...prevState,
    [id]: !prevState[id]
  }))
}

样式逻辑

export const DropdownContent = styled.div`
   /* 翻转显示逻辑:打开状态为block,关闭状态为none */
   display: ${({isOpen}) => isOpen ? 'block' : 'none'};
   position: absolute;
   background-color: white;
   min-width: 128px;
   box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
   z-index: 1;
`;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 19:24:03