React Window Infinite Loader

2.0.1 · active · verified Sun Apr 19

react-window-infinite-loader provides utilities for implementing infinite scrolling lists with `react-window`. It is inspired by `react-virtualized`'s `InfiniteLoader` but is specifically designed to work as a lightweight companion for `react-window`'s fixed and variable size lists. The current stable version is 2.0.1, released as of this documentation. The library's release cadence is tied to its maintainer's work on `react-window` and `react-virtualized`, often seeing updates for React compatibility or minor feature enhancements. Key differentiators include its tight integration with `react-window`, offering both a `useInfiniteLoader` hook for functional components and a `InfiniteLoader` component for class-based or render-prop patterns, making it adaptable to various component architectures. It helps manage the loaded state of rows and triggers data loading as users scroll near the end of the list.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates how to use the `useInfiniteLoader` hook with `react-window`'s `FixedSizeList` to implement a basic infinite scrolling list. It simulates fetching data asynchronously and updates the list as new rows are loaded.

import { useInfiniteLoader } from 'react-window-infinite-loader';
import { FixedSizeList } from 'react-window';
import React, { useState, useCallback } from 'react';

const Row = ({ index, style, isLoaded }) => (
  <div style={style}>
    {isLoaded ? `Row ${index}` : `Loading row ${index}...`}
  </div>
);

const ExampleList = ({ itemCount, isRowLoaded, loadMoreRows }) => {
  const [items, setItems] = useState(Array(itemCount).fill(false));

  const infiniteLoaderProps = {
    isRowLoaded,
    loadMoreRows,
    itemCount,
    threshold: 5,
    minimumBatchSize: 10
  };

  const onRowsRendered = useInfiniteLoader(infiniteLoaderProps);

  return (
    <FixedSizeList
      height={300}
      itemCount={itemCount}
      itemSize={50}
      width={500}
      onRowsRendered={onRowsRendered}
    >
      {({ index, style }) => (
        <Row index={index} style={style} isLoaded={isRowLoaded({ index })} />
      )}
    </FixedSizeList>
  );
};

function App() {
  const ROW_COUNT = 1000;
  const isItemLoaded = ({ index }) => index < loadedItems.length;
  const [loadedItems, setLoadedItems] = useState(Array(50).fill(true));

  const loadMore = useCallback(async (startIndex, stopIndex) => {
    console.log(`Loading rows from ${startIndex} to ${stopIndex}`);
    // Simulate API call
    await new Promise(resolve => setTimeout(resolve, 1000));

    setLoadedItems(prev => {
      const newItems = [...prev];
      for (let i = startIndex; i <= stopIndex; i++) {
        if (!newItems[i]) {
          newItems[i] = true;
        }
      }
      return newItems;
    });
  }, []);

  return (
    <ExampleList
      itemCount={ROW_COUNT}
      isRowLoaded={isItemLoaded}
      loadMoreRows={loadMore}
    />
  );
}

export default App;

view raw JSON →