Blog>
Snippets

Optimizing Large Lists with Dynamic Loading and TanStack Virtual

Demonstrate how to implement dynamic loading indicators and fetch data asynchronously for large lists managed by TanStack Virtual to optimize performance and user experience.
import { useVirtual } from '@tanstack/react-virtual';
import React, { useState, useEffect, useRef } from 'react';

function VirtualList({ fetchItems }) {
  const parentRef = useRef();
  const rowVirtualizer = useVirtual({
    size: 1000, // assuming a large list size
    parentRef,
    estimateSize: React.useCallback(() => 35, []), // estimate row height
  });

  // Function to fetch data when the last item is rendered
  useEffect(() => {
    const lastItemIndex = rowVirtualizer.virtualItems[rowVirtualizer.virtualItems.length - 1]?.index;
    if (lastItemIndex >= rowVirtualizer.totalSize - 10) { // Load more items before reaching the end
      fetchItems();
    }
  }, [fetchItems, rowVirtualizer.virtualItems, rowVirtualizer.totalSize]);

  return (
    <div ref={parentRef} style={{ height: '500px', overflow: 'auto' }}>
      <div style={{ height: rowVirtualizer.totalSize }}>
        {rowVirtualizer.virtualItems.map((virtualRow) => (
          <div key={virtualRow.index} style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            transform: `translateY(${virtualRow.start}px)`
          }}>
            {/* Render each row content */}
          </div>
        ))}
      </div>
    </div>
  );
}
This code snippet demonstrates how to set up a virtualized list using @tanstack/react-virtual. It establishes a virtualizer that manages the rendering of a large list in an efficient manner. The virtualizer only renders items in the DOM that are currently visible within the designated scrollable area (`parentRef`). It also includes logic to trigger more data to be fetched asynchronously from a `fetchItems()` function when the user scrolls close to the end of the list, improving the user experience by preemptively loading data before it's needed.