High-performance virtualization components for React that render large lists and grids efficiently by only showing visible items
—
One-dimensional virtualized scrolling component for efficiently rendering large lists of data by only rendering visible items in the viewport.
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 }}
/>
);
};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:
style prop must be applied to the root element of your row componentstyle contains positioning (top, left) and sizing (height, width) propertiesindex to access your data array or determine row contentProgrammatic 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>
);
};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