CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-window

High-performance virtualization components for React that render large lists and grids efficiently by only showing visible items

Pending
Overview
Eval results
Files

list-virtualization.mddocs/

List Virtualization

One-dimensional virtualized scrolling component for efficiently rendering large lists of data by only rendering visible items in the viewport.

Capabilities

List Component

Creates a virtualized list that renders only visible rows for optimal performance with large datasets.

/**
 * Virtualized list component for efficiently rendering large datasets
 * @param props - List configuration and rendering props
 * @returns Rendered list component
 */
function List<RowProps extends object>(props: ListProps<RowProps>): JSX.Element;

interface ListProps<RowProps extends object> {
  /** React component responsible for rendering a row */
  rowComponent: (props: { index: number; style: CSSProperties } & RowProps) => ReactNode;
  /** Number of items to be rendered in the list */
  rowCount: number;
  /** Row height in pixels, percentage, or function that returns height */
  rowHeight: number | string | ((index: number, rowProps: RowProps) => number);
  /** Additional props passed to the row-rendering component */
  rowProps: RowProps;
  /** Ref for accessing imperative API methods */
  listRef?: Ref<ListImperativeAPI>;
  /** Callback when visible row range changes */
  onRowsRendered?: (args: { startIndex: number; stopIndex: number }) => void;
  /** Callback when list container resizes */
  onResize?: (size: { height: number; width: number }, prevSize: { height: number; width: number }) => void;
  /** Additional rows to render outside visible area (default: 3) */
  overscanCount?: number;
  /** CSS class name for the list container */
  className?: string;
  /** CSS properties for the list container */
  style?: CSSProperties;
  /** Default height for server-side rendering */
  defaultHeight?: number;
}

Usage Examples:

import React from "react";
import { List } from "react-window";

// Basic list with fixed row height
const BasicList = () => {
  const items = Array.from({ length: 10000 }, (_, i) => `Item ${i}`);

  const RowComponent = ({ index, style }: { index: number; style: React.CSSProperties }) => (
    <div style={style}>
      {items[index]}
    </div>
  );

  return (
    <List
      rowComponent={RowComponent}
      rowCount={items.length}
      rowHeight={35}
      rowProps={{}}
      style={{ height: 400, width: 300 }}
    />
  );
};

// List with custom row props
interface ItemProps {
  isSelected: boolean;
  onClick: (index: number) => void;
}

const InteractiveList = () => {
  const [selectedIndex, setSelectedIndex] = React.useState<number | null>(null);
  const items = Array.from({ length: 1000 }, (_, i) => `Item ${i}`);

  const RowComponent = ({ 
    index, 
    style, 
    isSelected, 
    onClick 
  }: { 
    index: number; 
    style: React.CSSProperties;
  } & ItemProps) => (
    <div 
      style={{
        ...style,
        backgroundColor: isSelected ? '#e6f3ff' : 'white',
        cursor: 'pointer'
      }}
      onClick={() => onClick(index)}
    >
      {items[index]} {isSelected && '(Selected)'}
    </div>
  );

  return (
    <List
      rowComponent={RowComponent}
      rowCount={items.length}
      rowHeight={40}
      rowProps={{
        isSelected: (index: number) => index === selectedIndex,
        onClick: setSelectedIndex
      }}
      style={{ height: 400, width: 300 }}
    />
  );
};

// List with variable row heights
const VariableHeightList = () => {
  const items = Array.from({ length: 1000 }, (_, i) => 
    `Item ${i} - ${'Content '.repeat(Math.floor(Math.random() * 5) + 1)}`
  );

  const getRowHeight = (index: number) => {
    // Calculate height based on content length
    const contentLength = items[index].length;
    return Math.max(30, Math.ceil(contentLength / 30) * 20 + 10);
  };

  const RowComponent = ({ index, style }: { index: number; style: React.CSSProperties }) => (
    <div style={{ ...style, padding: '5px', wordWrap: 'break-word' }}>
      {items[index]}
    </div>
  );

  return (
    <List
      rowComponent={RowComponent}
      rowCount={items.length}
      rowHeight={getRowHeight}
      rowProps={{}}
      style={{ height: 400, width: 300 }}
    />
  );
};

Row Component Requirements

The component passed to rowComponent must accept specific props and handle styling correctly.

interface RowComponentProps<RowProps extends object = object> {
  /** Zero-based index of the row being rendered */
  index: number;
  /** CSS properties for positioning and sizing the row */
  style: CSSProperties;
}

type RowComponent<RowProps extends object> = (
  props: RowComponentProps & RowProps
) => ReactNode;

Important Notes:

  • The style prop must be applied to the root element of your row component
  • The style contains positioning (top, left) and sizing (height, width) properties
  • Do not override positioning properties in the style prop
  • Use index to access your data array or determine row content

List Imperative API

Programmatic control interface for the List component accessible via ref.

interface ListImperativeAPI {
  /** Get the outermost DOM element of the list */
  get element(): HTMLDivElement | null;
  
  /**
   * Scroll to a specific row index
   * @param params - Scroll configuration
   */
  scrollToRow(params: {
    index: number;
    align?: "auto" | "center" | "end" | "smart" | "start";
    behavior?: "auto" | "instant" | "smooth";
  }): void;
}

Usage Example:

import React, { useRef } from "react";
import { List, useListRef } from "react-window";

const ScrollableList = () => {
  const listRef = useListRef();

  const scrollToMiddle = () => {
    listRef.current?.scrollToRow({
      index: 500,
      align: "center",
      behavior: "smooth"
    });
  };

  const scrollToTop = () => {
    listRef.current?.scrollToRow({
      index: 0,
      align: "start",
      behavior: "smooth"
    });
  };

  return (
    <div>
      <button onClick={scrollToMiddle}>Scroll to Middle</button>
      <button onClick={scrollToTop}>Scroll to Top</button>
      
      <List
        listRef={listRef}
        rowComponent={RowComponent}
        rowCount={1000}
        rowHeight={35}
        rowProps={{}}
        style={{ height: 400, width: 300 }}
      />
    </div>
  );
};

Event Callbacks

The List component provides callbacks for monitoring visibility changes and resize events.

type OnRowsRendered = (args: { startIndex: number; stopIndex: number }) => void;

type OnResize = (
  size: { height: number; width: number },
  prevSize: { height: number; width: number }
) => void;

Usage Examples:

const MonitoredList = () => {
  const handleRowsRendered = ({ startIndex, stopIndex }: { startIndex: number; stopIndex: number }) => {
    console.log(`Rendering rows ${startIndex} to ${stopIndex}`);
    
    // Load more data when approaching the end
    if (stopIndex > items.length - 50) {
      loadMoreItems();
    }
  };

  const handleResize = (size: { height: number; width: number }) => {
    console.log(`List resized to ${size.width}x${size.height}`);
  };

  return (
    <List
      rowComponent={RowComponent}
      rowCount={items.length}
      rowHeight={35}
      rowProps={{}}
      onRowsRendered={handleRowsRendered}
      onResize={handleResize}
      style={{ height: 400, width: 300 }}
    />
  );
};

Install with Tessl CLI

npx tessl i tessl/npm-react-window

docs

grid-virtualization.md

imperative-apis.md

index.md

list-virtualization.md

typescript-utilities.md

tile.json