Skip to main content

Overview

TreeDataGrid is a component built on top of DataGrid to add hierarchical row grouping. This implements the Treegrid pattern.
import { TreeDataGrid, type Column } from 'react-data-grid';

interface Row {
  id: number;
  country: string;
  city: string;
  name: string;
}

const columns: readonly Column<Row>[] = [
  { key: 'country', name: 'Country' },
  { key: 'city', name: 'City' },
  { key: 'name', name: 'Name' }
];

function rowGrouper(rows: readonly Row[], columnKey: string): Record<string, readonly Row[]> {
  return Object.groupBy(rows, (row) => row[columnKey]);
}

function MyGrid() {
  const [expandedGroupIds, setExpandedGroupIds] = useState((): ReadonlySet<unknown> => new Set());

  return (
    <TreeDataGrid
      columns={columns}
      rows={rows}
      groupBy={['country', 'city']}
      rowGrouper={rowGrouper}
      expandedGroupIds={expandedGroupIds}
      onExpandedGroupIdsChange={setExpandedGroupIds}
    />
  );
}

How it works

  1. The groupBy prop specifies which columns should be used for grouping
  2. The rowGrouper function groups rows by the specified column keys
  3. Group rows are rendered with expand/collapse toggles
  4. Child rows are nested under their parent groups
  5. Groups can be expanded/collapsed by clicking the toggle or using keyboard navigation (, )

Keyboard Navigation

  • (Right Arrow): Expand a collapsed group row when focused
  • (Left Arrow): Collapse an expanded group row when focused, or navigate to parent group

Unsupported Props

The following DataGrid props are not supported in TreeDataGrid:
  • onFill - Drag-fill is disabled for tree grids
  • isRowSelectionDisabled - Row selection disabling is not available
  • role - TreeDataGrid manages the ARIA role
  • aria-rowcount - TreeDataGrid manages the ARIA row count

Caveats

  • Group columns cannot be rendered under one column
  • Group columns are automatically frozen and cannot be unfrozen
  • Cell copy/paste does not work on group rows
  • Column groups are not supported; columns must be Column[]

Props

All DataGridProps are supported except those listed above. Additional props specific to TreeDataGrid:
columns
readonly Column<R, SR>[]
required
An array of column definitions. Unlike DataGrid, column groups are not supported.
groupBy
readonly string[]
required
An array of column keys to group by. The order determines the grouping hierarchy (first key is the top level, second key is nested under the first, etc.).
<TreeDataGrid
  columns={columns}
  rows={rows}
  groupBy={['country', 'city']}
  rowGrouper={rowGrouper}
  expandedGroupIds={expandedGroupIds}
  onExpandedGroupIdsChange={setExpandedGroupIds}
/>
rowGrouper
(rows: readonly R[], columnKey: string) => Record<string, readonly R[]>
required
A function that groups rows by the specified column key. Returns an object where keys are the group values and values are arrays of rows belonging to that group.
function rowGrouper(rows: readonly Row[], columnKey: string): Record<string, readonly Row[]> {
  return Object.groupBy(rows, (row) => row[columnKey]);
}
expandedGroupIds
ReadonlySet<unknown>
required
A set of group IDs that are currently expanded. Group IDs are generated by groupIdGetter.
import { useState } from 'react';
import { TreeDataGrid } from 'react-data-grid';

function MyGrid() {
  const [expandedGroupIds, setExpandedGroupIds] = useState((): ReadonlySet<unknown> => new Set());

  return (
    <TreeDataGrid
      expandedGroupIds={expandedGroupIds}
      onExpandedGroupIdsChange={setExpandedGroupIds}
      // ... other props
    />
  );
}
onExpandedGroupIdsChange
(expandedGroupIds: Set<unknown>) => void
required
Callback triggered when groups are expanded or collapsed.
groupIdGetter
(groupKey: string, parentId?: string) => string
Function to generate unique IDs for group rows. If not provided, a default implementation is used that concatenates parent and group keys with __.Default implementation:
function defaultGroupIdGetter(groupKey: string, parentId: string | undefined) {
  return parentId !== undefined ? `${parentId}__${groupKey}` : groupKey;
}
rowHeight
number | ((args: RowHeightArgs<R>) => number)
Note: Unlike DataGrid, the rowHeight function receives RowHeightArgs<R> which includes a type property to distinguish between regular rows and group rows:
function getRowHeight(args: RowHeightArgs<Row>): number {
  if (args.type === 'GROUP') {
    return 50; // Custom height for group rows
  }
  return 35; // Height for regular rows
}

<TreeDataGrid rowHeight={getRowHeight} />

Generics

  • R - Row type
  • SR - Summary row type (default: unknown)
  • K - Row key type (default: Key)
interface Row {
  id: number;
  country: string;
  city: string;
}

function MyGrid() {
  return <TreeDataGrid<Row> columns={columns} rows={rows} groupBy={['country']} />;
}

Build docs developers (and LLMs) love