Row Virtualization
Mount only the visible row window inside a scrollable viewport so very large
datasets scroll smoothly. Mounted rows are real table rows sharing the header
<colgroup>, keeping header/body columns pixel-aligned and every interactive
element inside cells clickable at any scroll depth.
const table = useTable({
data,
columns,
enableVirtualization: true,
rowHeight: 40, // or (index) => number for variable heights
virtualViewportHeight: 480,
})
Notes
- Virtualization bypasses client pagination automatically — the whole
(sorted/grouped) dataset scrolls, so the old
pageSize: 100_000workaround is no longer needed.manualPagination(server-side) is still respected, and you should not combine virtualization with the<Pagination>control. virtualViewportHeightsets the scroll viewport in px; without it a heuristic (~20 rows, capped at 800px) applies, which can overflow shorter styled containers. Measure fixed-height panels and pass the available height explicitly.overscan(default 5) mounts extra rows around the window; exact per-row heights can come from Pretext viapretextHeights/pretextPrefixSums.- Pinned columns stay frozen to the viewport edges during horizontal
scroll: the header and body share one scroll container, so pinned header and
body cells move together. The horizontal scrollbar sits at the bottom of the
virtualViewportHeightviewport, reachable without scrolling to the last row. - The Pretext hooks (
useTableRowHeights,usePretextMeasurement) are imported from the@zvndev/yable-react/pretextsubpath and need the optional@chenglou/pretextpeer installed. The subpath keeps@chenglou/pretextout of the main entry, so importing@zvndev/yable-reactnever forces your bundler (e.g. Next.js/Turbopack) to resolve it:import { useTableRowHeights } from '@zvndev/yable-react/pretext'.