Blog>
Snippets

Handling Dynamic Row Heights in Virtualized Tables

Provide a code example to illustrate the approach for handling dynamic row heights in a virtualized table using TanStack Virtual, ensuring rows with variable content sizes are correctly measured and rendered.
const tableContainerRef = useRef(null);
Creates a React ref to attach to the table container. This ref is used to get the scrollable element for the virtualizer.
const { rows, newInvoiceIds } = useYourDataFetchingLogic();
Fetches the data for the rows in the table and any state or IDs you might need for your logic. Replace 'useYourDataFetchingLogic' with your actual data fetching hook.
const rowVirtualizer = useVirtualizer({
 count: rows.length,
 estimateSize: () => 33,
 getScrollElement: () => tableContainerRef.current,
 measureElement: typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1 ? (element) => element?.getBoundingClientRect().height : undefined,
 overscan: 5,
});
Initializes the row virtualizer with TanStack Virtual. 'estimateSize' provides an initial estimate for row heights. 'measureElement' dynamically measures row heights except in Firefox due to a specific measurement issue.
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
 const row = rows[virtualRow.index];
 return (
 <InvoiceTableRow
 row={row}
 isNewRow={newInvoiceIds.includes(row.original.invoiceId)}
 isSelectedRow={row.getIsSelected()}
 key={virtualRow.key}
 style={{
 top: 0,
 left: 0,
 width: '100%',
 position: 'absolute',
 transform: `translateY(${virtualRow.start}px)`,
 }}
 />
 );
})}
Renders the virtual rows using map over 'getVirtualItems'. Each row is positioned absolutely within the container using a transform that leverages the 'start' value provided by the virtualizer. Ensure each row component like 'InvoiceTableRow' is optimized and renders its children efficiently.