Blog>
Snippets

Implementing Virtual Scrolling in V8

Showcase the implementation of virtual scrolling with TanStack Table V8 to efficiently load and display large datasets, highlighting the differences from the previous approach in V7.
import { useVirtual } from '@tanstack/react-virtual';
First, import the useVirtual hook from TanStack's react-virtual package, which is responsible for the virtualization logic.
const table = useTable({
  data,
  columns,
  // other table options
});

const rowVirtualizer = useVirtual({
  size: table.getRowModel().rows.length,
  parentRef,
  estimateSize: useCallback(() => 35, []),
});
Initialize the table with useTable hook. Then, use the useVirtual hook to create a row virtualizer. You need to provide the total size (number of rows), a parent DOM element reference (parentRef), and an estimated size for each row.
return (
  <div {...getTableProps()} style={{ height: '400px', overflow: 'auto' }} ref={parentRef}>
    <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, width: '100%', position: 'relative' }}>
      {rowVirtualizer.getVirtualItems().map(virtualRow => (
        <div key={virtualRow.index} {...getRowProps({ rowIndex: virtualRow.index })} style={{
          position: 'absolute',
          top: 0,
          left: 0,
          width: '100%',
          transform: `translateY(${virtualRow.start}px)`
        }}>
          {table.getRowModel().rows[virtualRow.index].cells.map(cell => (
            <div {...cell.getCellProps()}>{cell.renderCell()}</div>
          ))}
        </div>
      ))}
    </div>
  </div>
);
Render the virtualized table. Use a container with a fixed height and overflow set to auto for the scrolling area. Inside, render another div that has a height set to the total size reported by the virtualizer. Map over the virtual rows and use absolute positioning to place them at their correct positions according to the virtualizer.