Documentation

Row Grouping

Row grouping allows you to organize your data into expandable hierarchical structures, making it easier to navigate large datasets with natural parent-child relationships.

Control Expansion:

Basic Setup

To enable row grouping, add the expandable: true property to your column header, structure your data with nested arrays, and specify the grouping hierarchy.

💡 Use Cases

  • Organize teams by department and show individual members
  • Display projects with their milestones and tasks
  • Show product categories with subcategories and items
  • Group transactions by account, invoice, and line items

🔑 Recommended: Use getRowId

When using row grouping with external sorting or dynamic data, it's highly recommended to provide the getRowId prop. This ensures stable row identification across data updates:

  • Maintains correct expansion state when data is sorted or filtered
  • Provides stable rowIdPath in onRowGroupExpand
  • Prevents row group collapse when row order changes
  • Essential for tables with external sorting enabled

Example: getRowId={({ row }) => row.id as string} or getRowId={({ row }) => row.uuid as string}

🎯 Need Different Columns at Each Level?

Row grouping shows child rows with the same columns as parent rows. If you need each level to have its own independent column structure (e.g., companies with 9 columns, divisions with 6 columns, teams with 19 columns), check out Nested Tables.

Row Grouping Configuration

PropertyRequiredDescriptionExample
HeaderObject.expandable
boolean
Optional
Makes a column expandable for grouping. This allows users to expand/collapse hierarchical data in that column.
rowGrouping
string[]
Optional
Array of property names that define the hierarchy levels. The order determines the nesting depth (first element is level 1, second is level 2, etc.).
expandAll
boolean
Optional
When true, all grouped rows are expanded by default on table load. When false, rows start collapsed.
Optional
Callback function triggered when a grouped row is expanded or collapsed. Receives detailed information including helper functions for managing loading, error, and empty states. The rowIndexPath array (v2.2.9+: contains ONLY numeric indices) provides a direct path to update nested data. The optional rowIdPath (when getRowId is provided) offers stable ID-based navigation. Perfect for lazy-loading hierarchical data on demand.
loadingStateRenderer
string | ReactNode
Optional
Custom content to render when a row is in loading state (set via setLoading helper in onRowGroupExpand). Can be a string or React component. If not provided, a default skeleton loading state will be shown automatically.
errorStateRenderer
string | ReactNode
Optional
Custom content to render when a row has an error state (set via setError helper in onRowGroupExpand). Can be a string or React component.
emptyStateRenderer
string | ReactNode
Optional
Custom content to render when a row has no children data (set via setEmpty helper in onRowGroupExpand). Can be a string or React component.
canExpandRowGroup
(row: Row) => boolean
Optional
Function to conditionally control whether a specific row group can be expanded. Return true to allow expansion, false to disable it. Useful for permission-based access, hiding empty groups, or business logic-based restrictions.

Programmatic Control

Version 2.1.0 introduces powerful programmatic control over row grouping expansion. You can now control which hierarchy levels are expanded or collapsed using the table ref API. These methods give you fine-grained control over the visibility of nested data.

🎯 New Table API Methods (v2.1.0)

  • expandAll() - Expand all rows at all depths
  • collapseAll() - Collapse all rows at all depths
  • expandDepth(depth) - Expand all rows at a specific depth (0-indexed)
  • collapseDepth(depth) - Collapse all rows at a specific depth (0-indexed)
  • toggleDepth(depth) - Toggle expansion for a specific depth
  • setExpandedDepths(depths) - Set which depths are expanded (replaces current state)
  • getExpandedDepths() - Get currently expanded depths as a Set
  • getGroupingProperty(depth) - Get the grouping property name for a depth index
  • getGroupingDepth(property) - Get the depth index for a grouping property name

Dynamic Row Loading

For large datasets, use the onRowGroupExpand callback to load nested data on-demand. This example demonstrates a three-level hierarchy (Regions → Stores → Products) where child rows are fetched from an API only when their parent is expanded. The callback provides powerful helper functions like setLoading, setError, and setEmpty for state management, plus rowIndexPath (v2.2.9+: contains only numeric indices) and rowIdPath (when getRowId is provided) for easy nested data updates.

💡 Benefits

  • Faster initial load - only top-level rows are fetched
  • Reduced memory usage - child data loaded as needed
  • Better performance with large hierarchical datasets
  • Seamless integration with server-side APIs
  • Built-in state management with setLoading, setError, and setEmpty helpers
  • Simple nested data updates using rowIndexPath array