如何控制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
相关产品推荐
相关产品推荐

