
本文详解如何在 MUI X Data Grid 中通过受控模式(controlled state)实现「展开全部」和「收起全部」按钮的稳定响应,彻底解决 defaultGroupingExpansionDepth 在动态交互后失效的问题。
本文详解如何在 mui x data grid 中通过受控模式(controlled state)实现「展开全部」和「收起全部」按钮的稳定响应,彻底解决 `defaultgroupingexpansiondepth` 在动态交互后失效的问题。
在使用 MUI X Data Grid 构建树形结构(treeData={true})时,开发者常希望通过按钮一键控制所有分组节点的展开/收起状态。虽然官方文档推荐使用 defaultGroupingExpansionDepth(如设为 -1 展开全部、0 收起全部),但该属性仅在组件初始化或重渲染时生效,无法响应运行时的交互变更——一旦用户手动点击某一行展开/收起,后续再点击“展开全部”按钮便不再触发更新,导致 UI 状态与预期脱节。
根本原因在于:defaultGroupingExpansionDepth 是非受控属性(uncontrolled),而树形网格的展开状态实际由内部状态管理。要实现可靠的全量控制,必须采用完全受控模式(controlled mode),即显式接管并同步 groupingExpansionState,并通过 onGroupingExpandedChange 响应用户操作。
✅ 正确实现方式:受控展开状态
以下是一个完整、可复用的解决方案:
import * as React from 'react';
import { DataGridPro, GridGroupingExpansionState } from '@mui/x-data-grid-pro';
import { Stack, Button } from '@mui/material';
// 定义状态常量(语义化提升可读性)
const EXPAND_ALL = true;
const COLLAPSE_ALL = false;
export default function ExpandCollapseAllGrid() {
const [expandedState, setExpandedState] = React.useState<GridGroupingExpansionState>(COLLAPSE_ALL);
const dataGridApi = React.useRef(null);
return (
<Stack spacing={2}>
{/* 控制按钮 */}
<Stack direction="row" spacing={1} p={1}>
<Button
variant="contained"
size="small"
onClick={() => setExpandedState(EXPAND_ALL)}
>
展开全部
</Button>
<Button
variant="outlined"
size="small"
onClick={() => setExpandedState(COLLAPSE_ALL)}
>
收起全部
</Button>
</Stack>
{/* 受控 DataGridPro */}
<DataGridPro
treeData
rows={rows} // 替换为你的树形数据(需含 `parentId` 字段)
columns={columns}
apiRef={dataGridApi}
// ? 关键:使用 groupingExpansionState 替代 defaultGroupingExpansionDepth
groupingExpansionState={expandedState}
// ? 关键:监听用户手动展开/收起行为,保持状态同步
onGroupingExpandedChange={(params) => {
// 注意:此处不直接设为 params.expanded,
// 因为用户单击某节点时,params.expanded 表示该节点新状态,
// 而我们维护的是全局统一状态(全展开 / 全收起)
// 所以建议:若需支持混合状态(部分展开),应改用 Map 管理各 groupId;
// 但本例聚焦「全量控制」,故保持布尔值语义
setExpandedState(params.expanded ? EXPAND_ALL : COLLAPSE_ALL);
}}
// 其他必要配置
getRowId={(row) => row.id}
getTreeDataPath={(row) => row.hierarchy || [row.id]} // 根据数据结构调整
disableSelectionOnClick
/>
</Stack>
);
}⚠️ 注意事项与最佳实践
-
groupingExpansionState 类型:其类型为 GridGroupingExpansionState(即 boolean | Record
)。上例中使用 boolean 是最简场景;若需更精细控制(例如仅展开某一层级或特定分组),应切换为 Record 并配合 groupId 管理。 - 避免与 defaultGroupingExpansionDepth 混用:二者互斥。启用 groupingExpansionState 后,请务必移除 defaultGroupingExpansionDepth,否则可能引发状态冲突或警告。
- 性能考量:对超大数据集(>5000 行),全量展开可能造成渲染卡顿。建议结合 pagination 或 virtualization(默认启用)确保流畅体验。
- 无障碍支持:MUI X 自动为展开/收起按钮添加 aria-expanded 和键盘导航(Enter/Space 触发),无需额外处理。
✅ 总结
defaultGroupingExpansionDepth 适用于静态初始态,而真正的交互式全量控制必须依赖受控属性 groupingExpansionState + onGroupingExpandedChange。该方案解耦了 UI 操作与内部状态,确保按钮无论在任何当前状态(全收起、部分展开、全展开)下均能可靠生效,是构建专业级树形数据网格的推荐实践。










