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

Material-UI表格点击展开按钮全部行展开,如何实现仅展开选中行?

问题

在Material-UI表格中,点击展开按钮时所有行都会同步展开/收起;点击行本身也会触发所有行展开。如何修改代码实现仅展开指定的单行?

原因分析

当前代码使用了一个全局的open布尔状态,所有行共享这个状态值。任何一行的展开按钮被点击时,都会修改这个全局状态,导致所有行的展开状态一起切换。

修改方案

为每一行维护独立的展开状态,用对象存储每行的展开状态(以行的唯一标识为键),而非单个布尔值。

修改后的完整代码
import { useState } from 'react';
import { Table, TableHead, TableRow, TableCell, TableBody, IconButton, Collapse } from '@mui/material';
import { KeyboardArrowUpIcon, KeyboardArrowDownIcon } from '@mui/icons-material';

export default function ExpandableTable({ data }) {
  // 用对象存储每行的展开状态,键为行的唯一ID,默认都不展开
  const [expandedRows, setExpandedRows] = useState({});

  // 切换指定行的展开状态
  const toggleRowExpansion = (rowId) => {
    setExpandedRows(prev => ({
      ...prev,
      [rowId]: !prev[rowId]
    }));
  };

  return (
    <Table stickyHeader aria-label="sticky table">
      <TableHead>
        <TableRow hover>
          <TableCell>展开</TableCell>
          <TableCell>Title</TableCell>
          <TableCell>Created Date</TableCell>
        </TableRow>
      </TableHead>
      <TableBody>
        {data?.map((row) => {
          const isExpanded = expandedRows[row.id] || false;
          return (
            <React.Fragment key={row.id}>
              <TableRow 
                hover 
                onClick={() => toggleRowExpansion(row.id)}
                style={{ cursor: 'pointer' }}
              >
                <TableCell>
                  <IconButton
                    aria-label="expand row"
                    size="small"
                    onClick={(e) => {
                      // 阻止事件冒泡,避免触发TableRow的点击事件
                      e.stopPropagation();
                      toggleRowExpansion(row.id);
                    }}
                  >
                    {isExpanded ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
                  </IconButton>
                </TableCell>
                <TableCell component="th" scope="row">
                  {row.title}
                </TableCell>
                <TableCell>
                  {new Date(row.createdDate.seconds * 1000).toDateString()}
                </TableCell>
              </TableRow>
              <TableRow>
                <TableCell colSpan={3}>
                  <Collapse in={isExpanded} timeout="auto" unmountOnExit>
                    {row.text}
                  </Collapse>
                </TableCell>
              </TableRow>
            </React.Fragment>
          );
        })}
      </TableBody>
    </Table>
  );
}
关键修改点
  • 替换全局open状态为expandedRows对象,每行的展开状态独立存储
  • 新增toggleRowExpansion函数,仅切换指定行的展开状态
  • 在IconButton的点击事件中添加e.stopPropagation(),避免触发TableRow的点击事件(若不需要点击行展开,可直接移除TableRow的onClick)
  • 使用行的唯一ID(row.id)作为状态标识,若数据无唯一ID,也可使用数组索引(index)替代
  • 将折叠内容放在单独的TableRow中,避免布局混乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:45:39