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

React Material UI实现点击ListItem展开时其他项折叠的方案

解决Material UI List点击单个项却展开所有项的问题

这个问题很典型——你现在应该是用了一个全局的布尔状态来控制所有列表项的展开/折叠,所以点击任何一项都会触发所有项的状态变化。咱们调整一下状态管理的方式就能轻松解决:

核心思路

把原来单一的布尔状态(比如expanded)改成跟踪当前展开项的唯一标识(比如国家的ID、名称或者索引),这样就能精准控制只有被点击的项切换展开/折叠状态。

修改步骤及代码示例

  1. 更新状态定义
    把原来的布尔状态替换为存储当前展开项的标识,初始值设为null表示没有项展开:

    import { useState } from 'react';
    // ...其他必要导入(比如List、ListItem、Collapse等)
    
    function YourListComponent() {
      // 用expandedId存储当前展开项的唯一标识,初始为null
      const [expandedId, setExpandedId] = useState(null);
      // ...其他代码(比如你的countries数据)
    }
    
  2. 修改点击事件处理函数
    点击列表项时,判断当前项的标识是否和expandedId一致:如果一致就折叠(设为null),不一致就展开(设为当前项的标识):

    const handleListItemClick = (itemId) => {
      setExpandedId(prevId => prevId === itemId ? null : itemId);
    };
    
  3. 调整列表项的展开判断逻辑
    在遍历渲染列表项时,给每个ListItem绑定点击事件,并让Collapse组件的in属性判断当前项的标识是否等于expandedId:

    {countries.map((country) => (
      <div key={country.id}>
        <ListItem button onClick={() => handleListItemClick(country.id)}>
          <ListItemText primary={country.name} />
          {/* 根据当前项是否展开切换图标 */}
          {expandedId === country.id ? <ExpandLess /> : <ExpandMore />}
        </ListItem>
        {/* 只有当expandedId等于当前项id时才展开 */}
        <Collapse in={expandedId === country.id} timeout="auto" unmountOnExit>
          <List component="div" disablePadding>
            <ListItem button className={classes.nested}>
              <ListItemText primary={`${country.name} 的子内容`} />
            </ListItem>
          </List>
        </Collapse>
      </div>
    ))}
    

为什么原来的方法无效?

你之前用索引尝试但没成功,大概率是因为还是沿用了单一布尔状态——不管是用索引还是其他标识,只要状态是全局的布尔值,所有项都会共享这个状态,导致点击一个全展开。而用唯一标识跟踪当前展开项,就能实现“点击哪项哪项展开,其余保持折叠”的预期效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:29:34