Blog>
Snippets

Implementing Infinite Loading with TanStack Virtual

Provide an example of how to implement infinite loading in a list by detecting when a user scrolls to the end of a virtualized list with TanStack Virtual.
import { useVirtualizer } from '@tanstack/react-virtual';
Import the useVirtualizer hook from TanStack Virtual.
const parentRef = React.useRef();
Create a ref for the scrolling parent container.
const [items, setItems] = React.useState([]); // Initial list of items
Initialize state to hold the list items.
const fetchMoreItems = async () => {
  // Fetch additional items and update state
  const newItems = await fetchNextItems();
  setItems((currentItems) => [...currentItems, ...newItems]);
};
Define an async function to fetch more items and append them to the current list.
const rowVirtualizer = useVirtualizer({
  count: items.length,
  getScrollElement: () => parentRef.current,
  overscan: 5,
  estimateSize: () => 50, // Assuming each item is 50px tall
  onScrollElementScrolled: (event) => {
    const scrollElement = event.currentTarget;
    if (scrollElement.scrollHeight - scrollElement.scrollTop === scrollElement.clientHeight) {
      fetchMoreItems();
    }
  }
});
Initialize the virtualizer with the list of items, the ref to the parent container, and an overscan. Use onScrollElementScrolled to detect when the scrollbar reaches the bottom and then call fetchMoreItems.
return (
  <div ref={parentRef} style={{ height: '500px', overflow: 'auto' }}>
    <div style={{ height: rowVirtualizer.getTotalSize() + 'px', position: 'relative' }}>
      {rowVirtualizer.getVirtualItems().map(virtualRow => (
        <div
          key={virtualRow.index}
          ref={virtualRow.measureRef}
          style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            transform: `translateY(${virtualRow.start}px)`
          }}
        >
          {items[virtualRow.index]}
        </div>
      ))}
    </div>
  </div>
);
Render the virtualized list inside the parent container. For each virtual item, create a div that positions itself absolutely within the relative container div according to the virtualRow's start position.