ReactJS嵌套列表:点击展开一项时其余项自动折叠
实现点击展开单个列表项,其余自动折叠
你的需求核心是同一时间只允许一个列表项处于展开状态,原有代码的问题在于每个列表项的展开状态独立存储,因此需要调整状态管理逻辑,改为记录当前唯一展开项的key。
修改步骤:
- 调整状态结构:把原来的
open: {}改为单个变量expandedKey,用来存储当前展开项的key,初始值设为null(表示无展开项)。 - 更新点击事件处理:点击列表项时判断当前项是否已展开:
- 若已展开,将
expandedKey设为null(折叠当前项) - 若未展开,将
expandedKey设为当前项的key(展开当前项,其余项自动折叠)
- 若已展开,将
- 修改展开状态判断:每个列表项的展开状态由
expandedKey是否等于自身key决定。
修改后的完整代码:
const lists = [ { key: "inbox", label: "Inbox", icon: InboxIcon, items: [ { key: "starred", label: "Starred", icon: StarBorder } ] }, { key: "drafts", label: "Drafts", icon: DraftsIcon, items: [{ key: "send", label: "Sent Items", icon: SendIcon }] } ]; const styles = theme => ({ root: { width: "100%", maxWidth: 360, backgroundColor: theme.palette.background.paper }, nested: { paddingLeft: theme.spacing.unit * 4 } }); class NestedList extends React.Component { // 改为记录单个展开的key state = { expandedKey: null }; handleClick = key => () => { this.setState(prevState => ({ // 如果当前key已展开则折叠,否则展开当前key expandedKey: prevState.expandedKey === key ? null : key })); }; render() { const { classes } = this.props; const { expandedKey } = this.state; return ( <div className={classes.root}> <List component="nav" subheader={ <ListSubheader component="div">Nested List Items</ListSubheader> } > {lists.map(({ key, label, icon: Icon, items }) => { // 判断当前项是否展开 const open = expandedKey === key; return ( <div key={key}> <ListItem button onClick={this.handleClick(key)}> <ListItemIcon> <Icon /> </ListItemIcon> <ListItemText inset primary={label} /> {open ? <ExpandLess /> : <ExpandMore />} </ListItem> <Collapse in={open} timeout="auto" unmountOnExit> <List component="div" disablePadding> {items.map(({ key: childKey, label: childLabel, icon: ChildIcon }) => ( <ListItem key={childKey} button className={classes.nested}> <ListItemIcon> <ChildIcon /> </ListItemIcon> <ListItemText inset primary={childLabel} /> </ListItem> ))} </List> </Collapse> </div> ); })} </List> </div> ); } }
关键改动说明:
- 状态从分散对象改为单个key,简化管理逻辑,天然保证同一时间仅一个项展开。
handleClick使用函数式更新setState,确保基于最新状态值判断,避免异步更新的状态偏差。- 每个列表项的
open状态直接通过对比expandedKey与自身key获取,逻辑清晰直观。
内容的提问来源于stack exchange,提问作者redouane
相关产品推荐
相关产品推荐

