React中如何实现仅同时打开一个UncontrolledCollapse并关闭其他
如何让Reactstrap的多个Collapse组件互斥展开(仅保持一个激活状态)
我在使用Reactstrap的UncontrolledCollapse组件时遇到问题:当存在多个该组件时,打开一个后再打开另一个,之前的不会自动关闭。需要实现点击某个toggle时,仅让对应的内容展开,同时关闭其他所有已展开的内容。
当前代码逻辑如下:
export default function Header(args) { return ( <Nav> <NavItem> <NavLink href="#" id="toggle-1"> Toggle 1 </NavLink> <UncontrolledCollapse toggler="#toggle-1"> Content 1 Here </UncontrolledCollapse> </NavItem> <NavItem> <NavLink href="#" id="toggle-2"> Toggle 2 </NavLink> <UncontrolledCollapse toggler="#toggle-2"> Content 2 Here </UncontrolledCollapse> </NavItem> </Nav> ) }
解决方案:改用受控的Collapse组件
UncontrolledCollapse是独立管理自身状态的,没法实现跨组件的状态同步。要实现互斥展开,需要改用受控的Collapse组件,通过父组件统一管理激活状态:
- 用
useState维护当前激活的collapse ID - 为每个toggle添加点击事件,更新激活状态为对应的ID
- 每个Collapse组件通过
isOpen属性判断是否为当前激活项
修改后的代码如下:
import { useState } from 'react'; import { Nav, NavItem, NavLink, Collapse } from 'reactstrap'; export default function Header(args) { // 初始化激活状态为null(全部关闭),或指定默认激活的ID(比如'toggle-1') const [activeCollapse, setActiveCollapse] = useState(null); const handleToggle = (toggleId) => { // 点击同一个toggle时切换状态,点击不同的则直接切换为目标ID setActiveCollapse(prev => prev === toggleId ? null : toggleId); }; return ( <Nav> <NavItem> <NavLink href="#" id="toggle-1" onClick={() => handleToggle('toggle-1')} > Toggle 1 </NavLink> <Collapse isOpen={activeCollapse === 'toggle-1'}> Content 1 Here </Collapse> </NavItem> <NavItem> <NavLink href="#" id="toggle-2" onClick={() => handleToggle('toggle-2')} > Toggle 2 </NavLink> <Collapse isOpen={activeCollapse === 'toggle-2'}> Content 2 Here </Collapse> </NavItem> </Nav> ) }
额外优化建议
如果有更多toggle项,可以把数据抽成数组循环渲染,避免重复代码:
const collapseItems = [ { id: 'toggle-1', label: 'Toggle 1', content: 'Content 1 Here' }, { id: 'toggle-2', label: 'Toggle 2', content: 'Content 2 Here' } ]; // 渲染时循环 {collapseItems.map(item => ( <NavItem key={item.id}> <NavLink href="#" id={item.id} onClick={() => handleToggle(item.id)} > {item.label} </NavLink> <Collapse isOpen={activeCollapse === item.id}> {item.content} </Collapse> </NavItem> ))}
内容的提问来源于stack exchange,提问作者Teik Cheah
相关产品推荐
相关产品推荐

