body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; line-height:1.6; color:#111; padding:20px; max-width:900px; margin:auto; }
pre { background:#f6f8fa; padding:12px; overflow:auto; border-radius:6px; }
code { font-family: SFMono-Regular, Menlo, Monaco, "Roboto Mono", monospace; background:#f6f8fa; padding:2px 4px; border-radius:4px; }
h1,h2 { color:#0b3d91; }
a { color:#0b66d0; }
.muted { color:#555; font-size:0.95em; }
.note { background:#fff8c6; padding:10px; border-left:4px solid #ffd54a; margin:12px 0; border-radius:4px; }
#semantic-core pre { white-space:pre-wrap; background:#f1f5f9; padding:10px; border-radius:6px; }
react-window: Efficient Virtualized Lists for Large React Datasets
A focused, practical guide to installing, using and optimizing react-window (with examples for FixedSizeList, VariableSizeList and infinite scroll).
Why use react-window (short version)
rendering thousands of DOM nodes kills performance and patience. react-window solves that by virtualizing the visible portion of a list — rendering only what’s visible (plus a small buffer). It’s minimalist, fast, and designed to be predictable.
Compared to older libraries like react-virtualized, react-window is smaller and simpler: fewer features but easier to reason about. If you need ultra-flexible layouts you might still use react-virtualized, but for most large-list scenarios react-window is the pragmatic winner.
Use cases: long chat histories, searchable tables, infinite feeds, file explorers — anywhere thousands of rows would otherwise overwhelm the browser.
Getting started: installation and basic setup
Install the package with npm or yarn. It’s tiny and has no runtime dependencies:
npm install react-window
# or
yarn add react-window
Then import the list component you need. The two most common are FixedSizeList and VariableSizeList. Use FixedSizeList when each item has the same height (fastest and simplest). Use VariableSizeList when heights vary.
Minimal scaffold: wrap the list in a fixed-height container (or let it size to available space) and pass itemCount and itemSize (for fixed) or an itemSize getter (for variable) along with a render callback (item renderer).
FixedSizeList example: most common pattern
FixedSizeList is ideal when every row has identical height. It’s the easiest to reason about and the fastest to calculate. The API is intentionally small: width, height, itemCount, itemSize, and a children function that receives an index and style object.
Key idea: react-window gives each item an inline style (position and transform) — apply that style to the root element you render for correct positioning. Do not ignore it or you'll get a broken layout.
import { FixedSizeList as List } from 'react-window';
function Row({ index, style }) {
return <div style={style}>Row #{index}</div>
}
<List
height={500}
itemCount={10000}
itemSize={35}
width={'100%'}
>
{Row}
</List>
Notes: set itemSize to the exact height in pixels (or a number). width can be a number or string like '100%'. Overscan is controllable with overscanCount to render extra items outside the viewport to smooth scrolling.
VariableSizeList: handling variable heights
VariableSizeList supports items with different heights by requiring a way to get each item’s size. You provide an itemSize function (or a list of sizes) and react-window calculates positions. It uses caches to avoid reflow cost, but when sizes change you must reset caches.
When items resize dynamically (images load or content changes), call resetAfterIndex(index, shouldForceUpdate) on the list ref so react-window recalculates layout. Avoid calling reset too often — batch updates where possible.
import { VariableSizeList as List } from 'react-window';
const sizes = new Array(1000).fill(0).map((_,i)=> 30 + (i % 5)*6);
function getSize(index) { return sizes[index]; }
<List
height={600}
itemCount={sizes.length}
itemSize={getSize}
width={800}
>
{({index, style}) => <div style={style}>Item {index}</div>}
</List>
Tip: measure dynamic content once (e.g., with ResizeObserver or a measurement pass) and cache sizes. That keeps render predictable and avoids layout thrash.
Infinite scroll and loading more items
react-window only handles rendering; infinite loading requires a loader that requests more data when the user scrolls near the end. The common combination is react-window + react-window-infinite-loader, which provides hooks for blocking and triggering loads while virtualized.
Pattern: keep an array with placeholders for not-yet-loaded items. Render placeholders in the virtual list. When the loader detects an index in the viewport that’s still a placeholder, it calls your loadMore function to fetch data and replace placeholders.
import InfiniteLoader from 'react-window-infinite-loader';
import { FixedSizeList as List } from 'react-window';
const isItemLoaded = index => !!items[index];
const loadMoreItems = (start, stop) => fetchMore(start, stop);
<InfiniteLoader
isItemLoaded={isItemLoaded}
itemCount={itemCount}
loadMoreItems={loadMoreItems}
>
{({ onItemsRendered, ref }) =>
<List
height={600}
itemCount={itemCount}
itemSize={40}
onItemsRendered={onItemsRendered}
ref={ref}
width={800}
>
{Row}
</List>
}
</InfiniteLoader>
Make sure your placeholder items have the same height as real items (or the layout will jump). Also guard against multiple parallel loads for the same range — the loader utilities help with that.
Performance best practices (practical checklist)
React-window helps a lot, but you can still shoot yourself in the foot. Follow these practical rules to keep scrolling buttery-smooth:
- Prefer FixedSizeList when possible. Variable sizes increase complexity.
- Memoize row renderers and use React.memo with a good compare to avoid unnecessary re-renders.
- Minimize the number of elements inside a row and avoid deep component trees that re-render on scroll.
Use overscanCount judiciously: higher overscan reduces frame drops at the cost of more DOM nodes. For mobile or low-power devices, reduce initial render work and avoid heavy synchronous code in render.
When combining with state updates (e.g., selection), isolate per-row state to prevent whole-list re-renders. Use itemKey via itemKey prop to maintain identity across operations.
Common pitfalls and how to avoid them
Don’t forget to apply the style prop passed to children — missing it breaks positioning. Also: avoid using percentage heights for items; react-window expects pixel heights to compute offsets precisely.
If you need complex layout (grids, masonry), consider react-window’s VariableSizeGrid or third-party wrappers — but test memory and layout cost first.
Watch out for virtualization + CSS transforms or fixed-position elements inside rows; these can clip or misplace content. When in doubt, isolate layers and test across browsers.
Resources and links (handy bookmarks)
Official repo and docs: react-window on GitHub. For comparisons and migration notes: react-virtualized repo. A practical tutorial: Getting started with react-window — dev.to.
If you’re using TypeScript, react-window has types bundled, but you’ll often need to type the item renderer props explicitly for best DX. For advanced use, explore outerElementType and innerElementType props to customize DOM wrappers.
FAQ
Q: How do I get started with react-window?
A: Install via npm/yarn, choose FixedSizeList or VariableSizeList, provide height, width, itemCount and itemSize, and render rows with the style prop. See the FixedSizeList example above.
Q: How do I virtualize variable-height items?
A: Use VariableSizeList and provide an itemSize getter (or array). If item heights change dynamically, measure them (ResizeObserver or initial render) and call resetAfterIndex on the list ref to update cache.
Q: How to implement infinite scroll with react-window?
A: Use react-window-infinite-loader or a custom onItemsRendered handler. Keep placeholders for not-yet-loaded items, trigger fetch when a visible index is missing, and replace placeholders with real data when loaded.
Semantic core (keyword clusters)
Primary keywords (main cluster):
react-window
React window virtualization
react-window tutorial
react-window installation
react-window example
react-window setup
react-window getting started
React large list rendering
React scroll performance
React list component
react-window FixedSizeList
react-window VariableSizeList
React infinite scroll
react-window FixedSizeList example
Secondary and long-tail (supporting / intent-driven):
react-window vs react-virtualized
react-window infinite loader
react-window performance optimization
react-window variable heights
react-window overscanCount
react-window itemSize function
react-window onItemsRendered
react-window resetAfterIndex
virtualized list React
rendering large lists React
best practices react-window
LSI, synonyms and related phrases:
virtualization in React
list virtualization
windowing
virtualized list
virtual list rendering
scroll virtualization
lazy rendering large lists
optimize React list rendering
avoid re-renders on scroll
memoize row components
Intent clusters:
Informational: react-window tutorial, React large list rendering, React scroll performance
Navigational: react-window GitHub, react-window docs, react-window installation
Commercial/Comparison: react-window vs react-virtualized, performance optimization
Transactional/Setup: react-window installation, react-window setup, react-window getting started
Authoritative links referenced
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "How do I get started with react-window?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Install react-window via npm or yarn, choose FixedSizeList or VariableSizeList, provide height, width, itemCount and itemSize (or itemSize getter), and render rows applying the provided style prop."
}
},
{
"@type": "Question",
"name": "How do I virtualize variable-height items?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Use VariableSizeList with an itemSize getter or size array. If items resize dynamically, measure them (for example with ResizeObserver) and call resetAfterIndex on the list ref to refresh layout caches."
}
},
{
"@type": "Question",
"name": "How to implement infinite scroll with react-window?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Combine react-window with react-window-infinite-loader or a custom onItemsRendered handler. Keep placeholders for unloaded items, trigger data fetch when placeholders enter the viewport, and replace placeholders with loaded data."
}
}
]
}
