Feature-rich and customizable data grid React component
Feature-rich and customizable data grid React component
[![npm-badge]][npm-url] [![type-badge]][npm-url] [![size-badge]][size-url] [![codecov-badge]][codecov-url] [![ci-badge]][ci-url]
The DataGrid component is designed to handle large datasets efficiently while offering a rich set of features for customization and interactivity.
color-scheme.Install react-data-grid using your favorite package manager:
npm i react-data-gridpnpm add react-data-gridyarn add react-data-gridbun add react-data-gridAdditionally, import the default styles in your application:
import 'react-data-grid/lib/styles.css';react-data-grid is published as ECMAScript modules for evergreen browsers, bundlers, and server-side rendering.
Important
Vite 8+ by default useslightningcssto minify css which has a bug minifying light-dark syntax. You can tweak thecssMinifyorcssTargetsettings as a workaround.
build: {
cssMinify: 'esbuild',
// or
cssTarget: 'esnext'
}Here is a basic example of how to use react-data-grid in your React application:
import 'react-data-grid/lib/styles.css';
import { DataGrid, type Column } from 'react-data-grid';
interface Row {
id: number;
title: string;
}
const columns: readonly Column<Row>[] = [
{ key: 'id', name: 'ID' },
{ key: 'title', name: 'Title' }
];
const rows: readonly Row[] = [
{ id: 0, title: 'Example' },
{ id: 1, title: 'Demo' }
];
function App() {
return <DataGrid columns={columns} rows={rows} />;
}The DataGrid provides multiple ways to customize its appearance and behavior.
The DataGrid supports both light and dark color schemes out of the box using the light-dark() CSS function. The theme automatically adapts based on the user's system preference when color-scheme: light dark; is set.
To enforce a specific theme, we recommend setting the standard color-scheme CSS property on the :root:
:root {
color-scheme: light; /* or 'dark', or 'light dark' for auto */
}Alternatively, you can add the rdg-light or rdg-dark class to individual grids:
// Force light theme
<DataGrid className="rdg-light" columns={columns} rows={rows} />
// Force dark theme
<DataGrid className="rdg-dark" columns={columns} rows={rows} />The DataGrid supports the following CSS variables for customization:
…Example of customizing colors:
.my-custom-grid {
--rdg-background-color: #f0f0f0;
--rdg-selection-color: #ff6b6b;
--rdg-font-size: 16px;
}<DataGrid className="my-custom-grid" columns={columns} rows={rows} />The DataGrid accepts standard className and style props:
<DataGrid
columns={columns}
rows={rows}
className="my-grid custom-theme"
style={{ width: 800, height: 600 }}
/>Control row heights using the rowHeight, headerRowHeight, and summaryRowHeight props. The rowHeight prop supports both fixed heights and dynamic heights per row.
Apply custom CSS classes to rows using the rowClass prop, and to header rows using the headerRowClass prop.
Apply custom CSS classes to cells using the cellClass property in column definitions. You can also use headerCellClass and summaryCellClass for header and summary cells respectively.
Control column widths using the width, minWidth, and maxWidth properties in column definitions. Enable column resizing using the resizable property, or use defaultColumnOptions to apply it to all columns.
Replace default components with custom implementations using the renderers prop. Columns can also have custom renderers using the renderCell, renderHeaderCell, renderSummaryCell, renderGroupCell, and renderEditCell properties.
<DataGrid />columns: readonly ColumnOrColumnGroup<R, SR>[]An array of column definitions and/or column groups. See the ColumnOrColumnGroup type for all available options.
:warning: Performance: Passing a new columns array will trigger a re-render and recalculation for the entire grid. Always memoize this prop using useMemo or define it outside the component to avoid unnecessary re-renders.
rows: readonly R[]An array of rows, the rows data can be of any type.
:bulb: Performance: The grid is optimized for efficient rendering:
Virtualization: Only visible rows are rendered in the DOM
Individual row updates: Row components are memoized, so updating a single row object will only re-render that specific row, not all rows
Array reference matters: Changing the array reference itself (e.g., setRows([...rows])) triggers viewport and layout recalculations, even if the row objects are unchanged
Best practice: When updating rows, create a new array but reuse unchanged row objects. For example:
// ✅ Good: Only changed row is re-rendered
setRows(rows.map((row, idx) => (idx === targetIdx ? { ...row, updated: true } : row)));
// ❌ Avoid: Creates new references for all rows, causing all visible rows to re-render
setRows(rows.map((row) => ({ ...row })));ref?: Maybe<React.Ref<DataGridHandle>>Optional ref for imperative APIs like scrolling to or focusing a cell. See DataGridHandle.
topSummaryRows?: Maybe<readonly SR[]>Rows pinned at the top of the grid for summary purposes.
:warning: Performance: Memoize this array to prevent internal memoization invalidation.
bottomSummaryRows?: Maybe<readonly SR[]>Rows pinned at the bottom of the grid for summary purposes.
:warning: Performance: Memoize this array to prevent internal memoization invalidation.
rowKeyGetter?: Maybe<(row: R) => K>Function to return a unique key/identifier for each row. rowKeyGetter is required for row selection to work.
import { DataGrid } from 'react-data-grid';
interface Row {
id: number;
name: string;
}
function rowKeyGetter(row: Row) {
return row.id;
}
function MyGrid() {
return <DataGrid columns={columns} rows={rows} rowKeyGetter={rowKeyGetter} />;
}:bulb: While optional, setting this prop is recommended for optimal performance as the returned value is used to set the key prop on the row elements.
:warning: Performance: Define this function outside your component or memoize it with useCallback to prevent unnecessary re-renders.
onRowsChange?: Maybe<(rows: R[], data: RowsChangeData<R, SR>) => void>Callback triggered when rows are changed.
The first parameter is a new rows array with both the updated rows and the other untouched rows.
The second parameter is an object with an indexes array highlighting which rows have changed by their index, and the column where the change happened.
import { useState } from 'react';
import { DataGrid } from 'react-data-grid';
function MyGrid() {
const [rows, setRows] = useState(initialRows);
return <DataGrid columns={columns} rows={rows} onRowsChange={setRows} />;
}rowHeight?: Maybe<number | ((row: R) => number)>Default: 35 pixels
Height of each row in pixels. A function can be used to set different row heights.
// Fixed height for all rows
<DataGrid columns={columns} rows={rows} rowHeight={50} />;
// Dynamic height per row
function getRowHeight(row) {
return row.isExpanded ? 100 : 35;
}
<DataGrid columns={columns} rows={rows} rowHeight={getRowHeight} />;:warning: Performance: When using a function, the heights of all rows are processed upfront. For large datasets (1000+ rows), this can cause performance issues if the identity of the function changes and invalidates internal memoization. Consider using a static function when possible, or memoize the rowHeight function.
headerRowHeight?: Maybe<number>Default: rowHeight when it is a number, otherwise 35 pixels
Height of the header row in pixels.
summaryRowHeight?: Maybe<number>Default: rowHeight when it is a number, otherwise 35 pixels
Height of each summary row in pixels.
<DataGrid
columns={columns}
rows={rows}
rowHeight={35}
headerRowHeight={45}
summaryRowHeight={40}
topSummaryRows={topSummaryRows}
/>columnWidths?: Maybe<ColumnWidths>A map of column widths contain
No open issues yet, or sync has not completed.