Skip to main content

Performance

The grid is built on the headless TanStack Table engine and renders with <div> + CSS Grid, so it's fast by default. These are the levers for large datasets and heavy cells.

Big datasets

RowsStrategy
Up to ~1,000 client-sideNothing special — client sorting / filtering / pagination is fine.
Thousands+ client-sideTurn on virtualization with a bounded height.
Very large / remoteUse server mode — hold one page in memory, let the backend sort / filter / page.
// Large client dataset:
<DataTable columns={columns} data={rows} enableVirtualization height={560} rowHeight={48} />

Keep references stable

Re-creating columns or data every render forces the engine to rebuild. Memoise them:

const columns = useMemo(() => [...], []); // stable unless the shape changes
const data = useMemo(() => transform(raw), [raw]); // only when the source changes
  • columns should be defined once (module scope or useMemo), never inline in JSX.
  • data should keep the same reference until it actually changes.
  • Provide getRowId (or idKey) so row identity survives re-sorts and refetches — selection, expansion, and editing all track rows by id.
<DataTable columns={columns} data={rows} getRowId={(row) => row.uuid} />

Cheap cells

Cells render often (scroll, sort, select). Keep them light:

  • Prefer column type and valueFormatter over a custom cell when you only need formatting — no React node is created.
  • If you do write cell, avoid heavy work and new object/array literals inside it.
  • Reach for wrapText / variable heights only where needed — uniform rowHeight scrolls the smoothest under virtualization.

Fixed vs. estimated row height

Under virtualization, a fixed rowHeight skips per-row measurement and gives the steadiest scrollbar. Use estimatedRowHeight only when rows genuinely vary (e.g. wrapText, detail panels) — set it close to the real height to minimise scroll jitter until rows measure.

Server mode tips

  • Debounce user input before calling onFetchData if your API is rate-limited.
  • Return an accurate total so pagination and export can page correctly.
  • Tune export paging with exportChunkSize / exportInterPageDelayMs for large server exports.

Persistence writes

State persistence is debounced (300 ms default). Raise persist.debounceMs for very chatty interactions, or narrow persist.include so only the slices you care about are written.