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

imperative-apis.mddocs/

Imperative APIs

Programmatic scrolling controls and DOM access for both List and Grid components through ref-based imperative APIs.

Capabilities

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 with customizable alignment and behavior
   * @param params - Scroll configuration
   */
  scrollToRow(params: {
    /** Zero-based index of the row to scroll to */
    index: number;
    /** How to align the row within the viewport */
    align?: "auto" | "center" | "end" | "smart" | "start";
    /** Scroll animation behavior */
    behavior?: "auto" | "instant" | "smooth";
  }): void;
}

Usage Examples:

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

// Using useListRef hook
const ListWithRef = () => {
  const listRef = useListRef();

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

  const getListElement = () => {
    const element = listRef.current?.element;
    if (element) {
      console.log("List container dimensions:", element.offsetWidth, element.offsetHeight);
    }
  };

  return (
    <div>
      <button onClick={() => scrollToRow(500)}>Scroll to Row 500</button>
      <button onClick={() => scrollToRow(0)}>Scroll to Top</button>
      <button onClick={getListElement}>Log Dimensions</button>
      
      <List
        listRef={listRef}
        rowComponent={RowComponent}
        rowCount={1000}
        rowHeight={35}
        rowProps={{}}
        style={{ height: 400, width: 300 }}
      />
    </div>
  );
};

// Using useListCallbackRef hook for shared refs
const ListWithCallbackRef = () => {
  const [listInstance, setListRef] = useListCallbackRef();

  React.useEffect(() => {
    if (listInstance) {
      // Scroll to middle on mount
      listInstance.scrollToRow({
        index: 250,
        align: "center",
        behavior: "instant"
      });
    }
  }, [listInstance]);

  return (
    <List
      listRef={setListRef}
      rowComponent={RowComponent}
      rowCount={500}
      rowHeight={40}
      rowProps={{}}
      style={{ height: 400, width: 300 }}
    />
  );
};

Grid Imperative API

Programmatic control interface for the Grid component accessible via ref with support for 2D scrolling.

interface GridImperativeAPI {
  /** Get the outermost DOM element of the grid */
  get element(): HTMLDivElement | null;
  
  /**
   * Scroll to a specific cell with customizable alignment for both dimensions
   * @param params - Scroll configuration for both row and column
   */
  scrollToCell(params: {
    /** Zero-based row index of the cell to scroll to */
    rowIndex: number;
    /** Zero-based column index of the cell to scroll to */
    columnIndex: number;
    /** How to align the row within the viewport */
    rowAlign?: "auto" | "center" | "end" | "smart" | "start";
    /** How to align the column within the viewport */
    columnAlign?: "auto" | "center" | "end" | "smart" | "start";
    /** Scroll animation behavior */
    behavior?: "auto" | "instant" | "smooth";
  }): void;
  
  /**
   * Scroll to a specific row index
   * @param params - Scroll configuration for row
   */
  scrollToRow(params: {
    /** Zero-based index of the row to scroll to */
    index: number;
    /** How to align the row within the viewport */
    align?: "auto" | "center" | "end" | "smart" | "start";
    /** Scroll animation behavior */
    behavior?: "auto" | "instant" | "smooth";
  }): void;
  
  /**
   * Scroll to a specific column index
   * @param params - Scroll configuration for column
   */
  scrollToColumn(params: {
    /** Zero-based index of the column to scroll to */
    index: number;
    /** How to align the column within the viewport */
    align?: "auto" | "center" | "end" | "smart" | "start";
    /** Scroll animation behavior */
    behavior?: "auto" | "instant" | "smooth";
  }): void;
}

Usage Examples:

import React, { useRef } from "react";
import { Grid, useGridRef, useGridCallbackRef } from "react-window";

// Using useGridRef hook
const GridWithRef = () => {
  const gridRef = useGridRef();

  const scrollToCell = (row: number, col: number) => {
    gridRef.current?.scrollToCell({
      rowIndex: row,
      columnIndex: col,
      rowAlign: "center",
      columnAlign: "center",
      behavior: "smooth"
    });
  };

  const scrollToCorners = () => {
    // Scroll to different corners with different alignments
    setTimeout(() => {
      gridRef.current?.scrollToCell({
        rowIndex: 0,
        columnIndex: 0,
        rowAlign: "start",
        columnAlign: "start",
        behavior: "smooth"
      });
    }, 0);

    setTimeout(() => {
      gridRef.current?.scrollToCell({
        rowIndex: 99,
        columnIndex: 49,
        rowAlign: "end",
        columnAlign: "end",
        behavior: "smooth"
      });
    }, 2000);
  };

  const scrollRowOnly = () => {
    gridRef.current?.scrollToRow({
      index: 25,
      align: "center",
      behavior: "smooth"
    });
  };

  const scrollColumnOnly = () => {
    gridRef.current?.scrollToColumn({
      index: 20,
      align: "center",
      behavior: "smooth"
    });
  };

  return (
    <div>
      <button onClick={() => scrollToCell(50, 25)}>Scroll to Center</button>
      <button onClick={scrollToCorners}>Tour Corners</button>
      <button onClick={scrollRowOnly}>Scroll to Row 25</button>
      <button onClick={scrollColumnOnly}>Scroll to Column 20</button>
      
      <Grid
        gridRef={gridRef}
        cellComponent={CellComponent}
        cellProps={{}}
        columnCount={50}
        columnWidth={100}
        rowCount={100}
        rowHeight={50}
        style={{ height: 400, width: 500 }}
      />
    </div>
  );
};

// Advanced usage with callback ref
const GridWithCallbackRef = () => {
  const [gridInstance, setGridRef] = useGridCallbackRef();
  const [currentCell, setCurrentCell] = React.useState({ row: 0, col: 0 });

  const navigateGrid = (direction: 'up' | 'down' | 'left' | 'right') => {
    if (!gridInstance) return;

    let newRow = currentCell.row;
    let newCol = currentCell.col;

    switch (direction) {
      case 'up':
        newRow = Math.max(0, currentCell.row - 1);
        break;
      case 'down':
        newRow = Math.min(99, currentCell.row + 1);
        break;
      case 'left':
        newCol = Math.max(0, currentCell.col - 1);
        break;
      case 'right':
        newCol = Math.min(49, currentCell.col + 1);
        break;
    }

    setCurrentCell({ row: newRow, col: newCol });
    
    gridInstance.scrollToCell({
      rowIndex: newRow,
      columnIndex: newCol,
      rowAlign: "smart",
      columnAlign: "smart",
      behavior: "smooth"
    });
  };

  return (
    <div>
      <div>Current Cell: {currentCell.row}, {currentCell.col}</div>
      <div>
        <button onClick={() => navigateGrid('up')}>↑</button>
        <button onClick={() => navigateGrid('down')}>↓</button>
        <button onClick={() => navigateGrid('left')}>←</button>
        <button onClick={() => navigateGrid('right')}>→</button>
      </div>
      
      <Grid
        gridRef={setGridRef}
        cellComponent={CellComponent}
        cellProps={{ currentCell }}
        columnCount={50}
        columnWidth={100}
        rowCount={100}
        rowHeight={50}
        style={{ height: 400, width: 500 }}
      />
    </div>
  );
};

Alignment Options

The alignment parameter controls how the target item is positioned within the viewport.

type Align = "auto" | "center" | "end" | "smart" | "start";

Alignment Behaviors:

  • "auto": Scroll minimally to bring the item into view
  • "center": Center the item in the viewport
  • "end": Align the item to the end of the viewport (bottom for rows, right for columns)
  • "smart": Minimize scrolling, but center if the item is smaller than the viewport
  • "start": Align the item to the start of the viewport (top for rows, left for columns)

Scroll Behavior Options

The behavior parameter controls the scroll animation using the native DOM ScrollBehavior type.

Scroll Behaviors:

  • "auto": Use the browser's default scrolling behavior
  • "instant": Jump immediately to the target position without animation
  • "smooth": Animate smoothly to the target position

DOM Element Access

Both APIs provide access to the underlying DOM element for advanced use cases.

// Get list container element
const listElement = listRef.current?.element;
if (listElement) {
  // Access DOM properties and methods
  console.log("Scroll position:", listElement.scrollTop);
  console.log("Client dimensions:", listElement.clientWidth, listElement.clientHeight);
  
  // Add event listeners
  listElement.addEventListener('scroll', handleScroll);
}

// Get grid container element
const gridElement = gridRef.current?.element;
if (gridElement) {
  // Access DOM properties
  console.log("Scroll position:", gridElement.scrollTop, gridElement.scrollLeft);
  
  // Measure dimensions
  const rect = gridElement.getBoundingClientRect();
  console.log("Element bounds:", rect);
}

Error Handling

The imperative APIs handle various edge cases gracefully:

const safeScrollToRow = (index: number) => {
  if (!listRef.current) {
    console.warn("List ref not available");
    return;
  }

  // Clamp index to valid range
  const clampedIndex = Math.max(0, Math.min(index, rowCount - 1));
  
  listRef.current.scrollToRow({
    index: clampedIndex,
    align: "center",
    behavior: "smooth"
  });
};

const safeScrollToCell = (row: number, col: number) => {
  if (!gridRef.current) {
    console.warn("Grid ref not available");
    return;
  }

  // Validate indices
  if (row < 0 || row >= rowCount || col < 0 || col >= columnCount) {
    console.warn("Invalid cell coordinates:", row, col);
    return;
  }

  gridRef.current.scrollToCell({
    rowIndex: row,
    columnIndex: col,
    rowAlign: "smart",
    columnAlign: "smart",
    behavior: "smooth"
  });
};

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