A few months ago, I was working on a React project, and everything was going well – until I had to display a very large list of items. At first, I thought, “It’s just a list, React can handle this easily.” But when I loaded 10,000+ items, the whole app started lagging. The scroll was slow, the UI became unresponsive, and I had no idea what was wrong.
But after some trial and error, I found a great solution: react-window. In this blog, I’ll share my personal experience using react-window to fix performance issues in React when rendering large lists.
The Problem: My App Was Too Slow
At first, I wrote a simple component to display a list of items similar like that:
function LargeList({ items }) {
return (
<div>
{items.map((item, index) => (
<div key={index} className="item">
{item}
</div>
))}
</div>
);
}
This worked fine for small lists (like 100 items), but when I tried 10,000 items, my browser froze. I couldn’t scroll smoothly, and everything felt slow.
I searched online and learned that React renders everything in the list at once, even items that are not visible. This means my browser was holding 10,000 DOM elements in memory, making the app slow.
The Solution: Virtualization with react-window
I found a library called react-window, which only renders the items that are visible on the screen. This technique is called virtualization, and it improves performance a lot.
How I Used react-window to Fix My App
Using FixedSizeList for a Large List
Since all my list items had the same height, I used FixedSizeList. Here’s how I updated my component:
import { FixedSizeList as List } from "react-window";
const items = Array.from({ length: 10000 }, (_, index) => `Item ${index}`);
function VirtualizedList() {
return (
<List
height={400} // The height of the visible area
itemCount={items.length} // Total number of items
itemSize={35} // Height of each item
width={300} // Width of the list
>
{({ index, style }) => (
<div style={style} className="item">
{items[index]}
</div>
)}
</List>
);
}
export default VirtualizedList;
After doing this, scrolling became super smooth! 🎉 Now, instead of rendering 10,000 items, React only renders the visible ones (about 10–15 items at a time).
What If List Items Have Different Heights?
I later worked on another project where the list items had different heights. For that, I had to use VariableSizeList instead of FixedSizeList.
Using VariableSizeList for Dynamic Heights
import { VariableSizeList as List } from "react-window";
const items = Array.from({ length: 10000 }, (_, index) => `Item ${index}`);
function VariableHeightList() {
const getItemSize = index => (index % 2 === 0 ? 50 : 75); // Alternate heights
return (
<List
height={400}
itemCount={items.length}
itemSize={getItemSize} // Function returning item height
width={300}
>
{({ index, style }) => (
<div style={style} className="item">
{items[index]}
</div>
)}
</List>
);
}
export default VariableHeightList;
This worked great, but I had to measure the height of each item manually.
Virtualized Tables: Handling Large Data Grids
Later, I needed to render large tables with 1,000 rows and 50 columns. Using a normal <table> made my app slow again. So, I used FixedSizeGrid for better performance.
Using FixedSizeGrid for Virtualized Tables
import { FixedSizeGrid as Grid } from "react-window";
const rowCount = 1000;
const columnCount = 50;
function VirtualizedTable() {
return (
<Grid
columnCount={columnCount}
columnWidth={100}
height={500}
rowCount={rowCount}
rowHeight={35}
width={600}
>
{({ columnIndex, rowIndex, style }) => (
<div style={style} className="cell">
{`R${rowIndex} C${columnIndex}`}
</div>
)}
</Grid>
);
}
export default VirtualizedTable;
Now, my table scrolled smoothly even with 50,000+ cells! 🚀
I hope you enjoy the coding.