or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-react-virtual

Hooks for virtualizing scrollable elements in React with support for rows, columns, and grids

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-virtual@3.13.x

To install, run

npx @tessl/cli install tessl/npm-react-virtual@3.13.0

index.mddocs/

React Virtual

React Virtual is a React hooks library that provides efficient virtualization capabilities for scrollable elements, enabling developers to render large lists and grids with optimal performance. The library offers a single headless hook (useVirtual) that supports row, column, and grid virtualization with flexible sizing options including fixed, variable, and dynamic measurements.

Package Information

  • Package Name: react-virtual
  • Package Type: npm
  • Language: JavaScript (with TypeScript support)
  • Installation: npm install react-virtual or yarn add react-virtual

Core Imports

import { useVirtual } from "react-virtual";

For CommonJS:

const { useVirtual } = require("react-virtual");

Basic Usage

import React from "react";
import { useVirtual } from "react-virtual";

function VirtualList() {
  const parentRef = React.useRef();

  const rowVirtualizer = useVirtual({
    size: 10000,
    parentRef: parentRef,
    estimateSize: React.useCallback(() => 35, []),
  });

  return (
    <div
      ref={parentRef}
      style={{
        height: "200px",
        width: "400px",
        overflow: "auto",
      }}
    >
      <div
        style={{
          height: `${rowVirtualizer.totalSize}px`,
          width: "100%",
          position: "relative",
        }}
      >
        {rowVirtualizer.items.map((virtualRow) => (
          <div
            key={virtualRow.index}
            style={{
              position: "absolute",
              top: 0,
              left: 0,
              width: "100%",
              height: `${virtualRow.size}px`,
              transform: `translateY(${virtualRow.start}px)`,
            }}
          >
            Row {virtualRow.index}
          </div>
        ))}
      </div>
    </div>
  );
}

Architecture

React Virtual is built around a single, powerful hook that manages virtualization state:

  • Measurement System: Tracks item sizes using either fixed estimates or dynamic measurements
  • Viewport Calculation: Determines which items are visible based on scroll position and container size
  • Overscan Management: Renders additional items beyond the visible area for smooth scrolling
  • Imperative Scrolling: Provides functions to programmatically scroll to specific items or offsets
  • Orientation Support: Handles both vertical (default) and horizontal virtualization

Capabilities

useVirtual Hook

The main virtualization hook that manages the rendering of large lists, grids, and columns with optimal performance.

/**
 * Main virtualization hook for efficient rendering of large datasets
 * @param options - Configuration object for virtualization behavior
 * @returns Object containing virtual items and control functions
 */
function useVirtual(options: VirtualOptions): VirtualResult;

interface VirtualOptions {
  /** Total number of items to virtualize (required) */
  size: number;
  /** Reference to the scrollable parent element (required) */
  parentRef: React.RefObject<HTMLElement>;
  /** Function to estimate size of each item (required, must be memoized with useCallback) */
  estimateSize: (index: number) => number;
  /** Number of items to render beyond visible area (default: 1) */
  overscan?: number;
  /** Enable horizontal virtualization using width/scrollLeft (default: false) */
  horizontal?: boolean;
}

interface VirtualResult {
  /** Array of currently visible virtual items */
  items: VirtualItem[];
  /** Total size of all virtualized content in pixels */
  totalSize: number;
  /** Function to scroll to a specific pixel offset */
  scrollToOffset: (offset: number) => void;
  /** Function to scroll to a specific item index */
  scrollToIndex: (index: number) => void;
}

interface VirtualItem {
  /** Zero-based index of the item */
  index: number;
  /** Starting position in pixels */
  start: number;
  /** Item size in pixels */
  size: number;
  /** Ending position in pixels */
  end: number;
  /** Ref callback for dynamic measurement */
  measureRef: (element: HTMLElement | null) => void;
}

Usage Patterns:

Row Virtualization (Vertical Lists):

const rowVirtualizer = useVirtual({
  size: 10000,
  parentRef: parentRef,
  estimateSize: React.useCallback(() => 35, []),
  overscan: 5,
});

Column Virtualization (Horizontal Lists):

const columnVirtualizer = useVirtual({
  horizontal: true,
  size: 1000,
  parentRef: parentRef,
  estimateSize: React.useCallback(() => 100, []),
  overscan: 5,
});

Grid Virtualization (2D Virtualization):

// Use two separate hooks for rows and columns
const rowVirtualizer = useVirtual({
  size: 10000,
  parentRef: parentRef,
  estimateSize: React.useCallback(() => 35, []),
  overscan: 5,
});

const columnVirtualizer = useVirtual({
  horizontal: true,
  size: 10000,
  parentRef: parentRef,
  estimateSize: React.useCallback(() => 100, []),
  overscan: 5,
});

// Render grid by mapping over both virtualizers
return (
  <div ref={parentRef} style={{ height: "500px", width: "500px", overflow: "auto" }}>
    <div
      style={{
        height: `${rowVirtualizer.totalSize}px`,
        width: `${columnVirtualizer.totalSize}px`,
        position: "relative",
      }}
    >
      {rowVirtualizer.items.map((virtualRow) => (
        <React.Fragment key={virtualRow.index}>
          {columnVirtualizer.items.map((virtualColumn) => (
            <div
              key={virtualColumn.index}
              style={{
                position: "absolute",
                top: 0,
                left: 0,
                width: `${virtualColumn.size}px`,
                height: `${virtualRow.size}px`,
                transform: `translateX(${virtualColumn.start}px) translateY(${virtualRow.start}px)`,
              }}
            >
              Cell {virtualRow.index}, {virtualColumn.index}
            </div>
          ))}
        </React.Fragment>
      ))}
    </div>
  </div>
);

Dynamic Measurement:

// For items with unknown sizes, use measureRef for runtime measurement
{rowVirtualizer.items.map((virtualRow) => (
  <div
    key={virtualRow.index}
    ref={virtualRow.measureRef}
    style={{
      position: "absolute",
      top: 0,
      left: 0,
      width: "100%",
      transform: `translateY(${virtualRow.start}px)`,
    }}
  >
    Content with dynamic height...
  </div>
))}

Imperative Scrolling:

// Scroll to specific item
const scrollToItem = (index) => {
  rowVirtualizer.scrollToIndex(index);
};

// Scroll to specific offset
const scrollToTop = () => {
  rowVirtualizer.scrollToOffset(0);
};

Key Features

  • Performance Optimized: Only renders visible items plus overscan, dramatically reducing DOM nodes
  • Flexible Sizing: Supports fixed, variable, and dynamic item sizing
  • Multi-directional: Handles vertical (default) and horizontal virtualization
  • Grid Support: Combine row and column virtualizers for 2D grids
  • Smooth Scrolling: Configurable overscan prevents visual gaps during fast scrolling
  • Imperative Control: Programmatic scrolling to specific items or positions
  • Framework Agnostic: Pure React hook with no additional dependencies beyond React
  • TypeScript Ready: Full type definitions for enhanced development experience

Error Handling

The hook expects:

  • estimateSize to be memoized with React.useCallback() to prevent unnecessary re-calculations
  • parentRef to reference an element with overflow: auto or overflow: scroll
  • size to be a positive integer representing the total number of items

If these requirements aren't met, the virtualization may not work correctly or performance may be degraded.