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.