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

如何实现Material-UI表格仅点击对应行时才单独展开

问题原因

你当前所有行共用了同一个open布尔状态,只要这个状态变更,所有行的展开/收起状态都会同步变更,才会出现点第一行第二行也跟着展开的问题。

修复方案

把单一的布尔状态改为存储当前展开行的唯一标识(如果要支持同时展开多行可以用数组存储多个标识),点击时仅更新对应行的标识匹配状态即可。

步骤1:修改状态定义

如果你的每条数据有唯一id字段推荐用id,没有的话可以临时用数组索引:

// 单选展开(一次只能展开一行)
const [openRowId, setOpenRowId] = useState(null);

// 如果要支持同时展开多行,用数组存
// const [openRowIds, setOpenRowIds] = useState([]);

步骤2:修改点击事件和展开判断

同时修正你原代码里data遍历的语法错误,原代码写的data((index) =>)应为data.map((item, index) =>):

<Table stickyHeader aria-label="sticky table">
  <TableHead>
    <TableRow hover>
      <TableCell>Title</TableCell>
      <TableCell>Created Date</TableCell>
    </TableRow>
  </TableHead>
  <TableBody>
  {data &&
   data.map((item, index) => (
    <TableRow hover key={item.id || index}> {/* 必须加唯一key */}
      <TableCell>
        <IconButton
          aria-label="expand row"
          size="small"
          onClick={() => {
            // 单选展开逻辑
            setOpenRowId(openRowId === (item.id || index) ? null : (item.id || index))
            
            // 多选展开逻辑
            /*
            setOpenRowIds(prev => {
              const id = item.id || index
              return prev.includes(id) ? prev.filter(v => v !== id) : [...prev, id]
            })
            */
          }}
          >
          {/* 单选判断 */}
          {openRowId === (item.id || index) ? (
            <KeyboardArrowUpIcon />
          ) : (
            <KeyboardArrowDownIcon />
          )}
          {/* 多选判断 */}
          {/* {openRowIds.includes(item.id || index) ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} */}
          </IconButton>
        </TableCell>
        <TableCell component="th" scope="row">
          {item.title}
        </TableCell>
        <TableCell component="th" scope="row">
          {new Date(
            item.createdDate.seconds * 1000
          ).toDateString()}
        </TableCell>
        <TableCell colSpan={6}>
          {/* 单选in属性 */}
          <Collapse in={openRowId === (item.id || index)} timeout="auto" unmountOnExit>
            {item.text}
          </Collapse>
          {/* 多选in属性 */}
          {/* <Collapse in={openRowIds.includes(item.id || index)} timeout="auto" unmountOnExit>
            {item.text}
          </Collapse> */}
        </TableCell>
      </TableRow>
     ))}
   </TableBody>
 </Table>

注意事项

  • 遍历渲染TableRow时必须加唯一key属性,否则React渲染列表时也可能出现状态串位的问题
  • 优先用数据本身的唯一id作为标识,不要默认用数组索引,如果你有列表排序、删除、新增的需求,用索引会导致标识对应错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 01:30:02