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

ReactJS嵌套列表:点击展开一项时其余项自动折叠

实现点击展开单个列表项,其余自动折叠

你的需求核心是同一时间只允许一个列表项处于展开状态,原有代码的问题在于每个列表项的展开状态独立存储,因此需要调整状态管理逻辑,改为记录当前唯一展开项的key。

修改步骤:

  1. 调整状态结构:把原来的open: {}改为单个变量expandedKey,用来存储当前展开项的key,初始值设为null(表示无展开项)。
  2. 更新点击事件处理:点击列表项时判断当前项是否已展开:
    • 若已展开,将expandedKey设为null(折叠当前项)
    • 若未展开,将expandedKey设为当前项的key(展开当前项,其余项自动折叠)
  3. 修改展开状态判断:每个列表项的展开状态由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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 19:15:50