-
Notifications
You must be signed in to change notification settings - Fork 0
Performance
📝 Generated from
docs/performance.md. Edit it there; changes made in the wiki are overwritten.
Tips for getting the most out of OpenGridX with large datasets.
The most common cause of unnecessary re-renders is a new column array being created on every render.
// ✅ Good: stable reference
const columns = useMemo<GridColDef[]>(() => [
{ field: 'id', headerName: 'ID', width: 70 },
{ field: 'name', headerName: 'Name', width: 200 },
], []);
// ❌ Bad: new array on every render → column layout is recomputed every render
const columns = [
{ field: 'id', headerName: 'ID', width: 70 },
{ field: 'name', headerName: 'Name', width: 200 },
];The same applies to the rows prop — if you derive rows from server data, wrap the derivation in useMemo.
renderCell is called for every visible cell on every render. Expensive work inside it multiplies with overscan.
// ✅ Good: memoized sub-component
const StatusBadge = React.memo(({ value }: { value: string }) => (
<span className={`badge badge--${value}`}>{value}</span>
));
{ field: 'status', renderCell: (p) => <StatusBadge value={String(p.value)} /> }
// ❌ Bad: inline object / new function reference every render
{ field: 'status', renderCell: (p) => <span style={{ color: 'red' }}>{String(p.value)}</span> }Every row has the same height (rowHeight or the density preset); there is no per-row height callback. Expanded detail panels add their own height, which the grid folds into a cumulative-height table, so many expanded panels (and 'auto' panels, which are measured after they render) cost more than plain rows.
// Fixed height — fastest
<DataGrid rows={rows} columns={columns} rowHeight={48} />
// Variable height — necessary for detail panels, but adds cost
<DataGrid rows={rows} columns={columns} getDetailPanelHeight={() => 200} />density="compact" and density="comfortable" replace rowHeight with a preset (32 px / 72 px, or the theme's grid.rowHeightCompact / grid.rowHeightComfortable); density="standard" uses rowHeight. Compact rows fit more rows in the viewport.
<DataGrid density="compact" /> // 32 px rows — more rows in viewport
<DataGrid density="standard" /> // rowHeight (default 52 px)
<DataGrid density="comfortable" /> // 72 px rowsoverscanRowCount (default 3) is the minimum rows rendered outside the viewport. The grid raises it automatically based on scroll velocity. Raise the floor only if you still see blank flashes at the default.
// Raise the floor for very fast scrolling environments
<DataGrid overscanRowCount={8} rows={rows} columns={columns} />See Virtualization for the full adaptive-overscan details.
autoHeight sizes the grid to all of its rows, so every row is rendered. Only use it when the dataset is small (< 100 rows), or together with pagination.
Virtualization only works when the viewport has a fixed height: pass height, or put the grid in a container with a definite height (a flex child needs min-height: 0). In an unbounded container the viewport grows to fit every row and every row is rendered; a dev-mode warning reports this.
The same happens when the stylesheet is missing, because the viewport's overflow: auto comes from it (a dev-mode warning reports a missing stylesheet too). Import it once in your app:
import '@opencorestack/opengridx/styles';The grid sizes its scroll content to rowCount × rowHeight pixels and does not scale scroll positions. Browsers cap an element's height (Chromium at 33,554,432 px, Firefox lower), so at the default 52 px row height rows past roughly 645,000 cannot be scrolled to. A dev-mode warning reports it. For more rows, use pagination, paginationMode="server" or infinite scroll with a dataSource.
Client-side filtering, sorting, and pagination load the full dataset into JS. For very large datasets, prefer server-side modes. The simplest way is a dataSource: the grid calls getRows with the page range, sort model and filter model, and shows the response (see Server-Side Data).
Without a dataSource, fetch the rows yourself from the change callbacks and control the models:
<DataGrid
rows={pageRows} // the current page, already filtered and sorted by the server
columns={columns}
filterMode="server"
sortingMode="server"
pagination
paginationMode="server"
rowCount={totalRows} // server total
paginationModel={paginationModel}
onPaginationModelChange={setPaginationModel} // refetch in an effect on these models
sortModel={sortModel}
onSortModelChange={setSortModel}
filterModel={filterModel}
onFilterModelChange={setFilterModel}
/>In server modes the grid shows rows as given: it does not re-filter, re-sort or slice them (v3.0+; earlier versions did unless a dataSource was set).
OpenGridX 3.2.2 · MIT · This wiki is generated from docs/ on every push to main. To fix a page, open a PR against the source file.
Start here
Components
- DataGrid
- Header
- Row
- Cell
- Toolbar
- Pagination
- Filter Panel
- Tooltip
- Column Visibility
- Column Grouping
- Column Resizing
- Empty State
- Error Overlay
- Aggregation Footer
Features
- Virtualization
- Filtering & Search
- Sorting & Pagination
- Custom Pagination
- Editing & Reordering
- Row Selection
- Clipboard
- Pinning
- State Persistence
- Aggregation & Pivot
- Tree Data & Grouping
- Cell Spanning
- Master-Detail
- Keyboard & Accessibility
- List View
- Infinite Scroll
- Data Source
- Loading States
- Toolbar Customization
- Export (CSV, Excel, JSON, Print)
- PDF Export
Customization
Upgrading
Contributing
- Contributing
- Testing
- Roadmap
- DataGrid orchestration
- GridRowMeta
- useGridControlledState
- useGridRowPipeline
- useGridColumns
- useGridVirtualization
- useGridVisibleRows
- useGridScrollSync
- useGridStateSnapshot