如何实现React表格仅被点击行触发Collapse折叠效果
问题根因
所有表格行共用了同一个布尔类型的open状态:
- 任意行的按钮点击时,修改的都是这同一个全局状态
- 所有行的
Collapse组件的展开控制属性in都绑定了这个open值,因此会同步触发展开/收起逻辑,无法实现单行独立控制。
修复方案
根据交互需求二选一即可:
方案1:单展开模式(同一时间仅允许展开一行)
不再存储布尔值,改为存储当前展开行的唯一id,默认值为null(默认无展开行)。
- 替换原有状态定义:
// 替换原来的 const [open, setOpen] = useState(false) const [openRowId, setOpenRowId] = useState<string | number | null>(null);
- 修改行渲染逻辑,仅当当前行id和存储的展开id一致时,才触发展开、渲染对应方向的图标:
{data.map((dataRow) => ( <TableRow key={dataRow.id} title="tableRow" className={classes.tableRow} > <TableCell className={classes.tableCell}> <IconButton size="small" onClick={() => { // 点击当前已展开的行则收起,否则展开当前行、自动收起其他行 setOpenRowId(openRowId === dataRow.id ? null : dataRow.id) }} > {openRowId === dataRow.id ? <ArrowDropDownIcon /> : <ArrowDropUpIcon />} </IconButton> {dataRow.id} <Collapse in={openRowId === dataRow.id} timeout="auto" unmountOnExit> <Box margin={1}> <Typography variant="h6" gutterBottom component="div"> History </Typography> </Box> </Collapse> </TableCell> <TableCell className={classes.tableCell}> {dataRow.name} </TableCell> <TableCell align="left" className={classes.tableCell}> {dataRow.lastName} </TableCell> </TableRow> ))}
方案2:多展开模式(支持同时展开多行)
存储所有处于展开状态的行id集合,点击时切换当前行id在集合中的存在状态即可。
- 替换原有状态定义:
const [openRowIds, setOpenRowIds] = useState<Set<string | number>>(new Set());
- 修改行渲染逻辑:
<IconButton size="small" onClick={() => { setOpenRowIds(prev => { const newOpenSet = new Set(prev); // 已展开则移除id(收起),未展开则加入id(展开) if (newOpenSet.has(dataRow.id)) { newOpenSet.delete(dataRow.id) } else { newOpenSet.add(dataRow.id) } return newOpenSet }) }} > {openRowIds.has(dataRow.id) ? <ArrowDropDownIcon /> : <ArrowDropUpIcon />} </IconButton> {/* Collapse 组件的in属性同步修改为 */} <Collapse in={openRowIds.has(dataRow.id)} timeout="auto" unmountOnExit> {/* 折叠内容保持不变 */} </Collapse>
内容的提问来源于stack exchange,提问作者Tanu
相关产品推荐
相关产品推荐

