Blog #15: The 10,000-Row Lesson – When Table Virtualization saved my career
To my early large-data days, when rendering 5000 rows of data literally made the browser smoke.
Hey there, my younger, "fiery" self from a few years ago.
I remember when the boss tasked you with displaying the entire inventory of a supermarket chain—about 15,000 items. You smiled confidently: "Easy, boss, I'll just use map() and it's done!". You excitedly coded, and sure enough, locally with 10 test rows, it ran lightning fast. You happily deployed to Production.
But when the real 15,000-row data flooded in, your browser suddenly froze. The mouse wouldn't move even 1mm. Google Chrome reported "Out of Memory" and crashed the computers of dozens of warehouse staff. You turned pale, not understanding what you'd done wrong when the "code was clearly correct in logic."
1. Simple Explanation: The Story of an Endless List
Imagine you're standing and reading a list of 15,000 names.
Your old way was: Spread the entire 3km-long paper on the ground and try to see everything at once. The browser is the one who has to "draw" all 15,000 names into memory. Each name is a set of HTML tags (div, span, tr, td). 15,000 rows multiplied by 10 columns—you just forced the browser to manage 150,000 DOM nodes. That's an overwhelming burden for any computer.
2. Current Perspective: Why Virtualization is a Miracle?
The truth is: human eyes can only see about 10-20 rows on the screen at a time. So why do we have to draw the 14,980 rows that the user hasn't seen (or will never see)?
Virtualization works on an extremely smart principle:
- You draw only the 20 rows currently visible.
- As the user scrolls down, you quickly "reuse" old rows, replace them with new data, and push them down.
- The user still sees an incredibly long scrollbar (thanks to a hollow div tag with height equal to 15,000 rows), but in reality, the browser memory only has to carry 20-30 HTML tags.
3. Concrete Example: The map() method trap
You used to write like this:
// Junior's way: "All-in-one" and shutdown
const BigTable = ({ data }) => {
return (
<div className="table-container">
{data.map(item => (
<Row key={item.id} {...item} />
// 15,000 components initialized at once!
))}
</div>
);
};
Why is this a problem? Because even when you can't see everything, the browser still has to calculate layout and style and manage events for every node. Just one keystroke in the search bar, and React will have to compare those 15,000 nodes. Lag is inevitable.
Sustainable Approach (Virtual List):
import { FixedSizeList as List } from 'react-window';
const BigTable = ({ data }) => {
const Row = ({ index, style }) => (
<div style={style}>
{index}: {data[index].name}
</div>
);
return (
<List
height={600}
itemCount={data.length}
itemSize={35}
width={1000}
>
{Row}
{/* Renders only about 15-20 Rows at any given time */}
</List>
);
};
4. Comparison: "Doing it Fast" vs "Doing it Sustainably"
| Criteria | Doing it Fast (Direct Map) | Doing it Sustainably (Virtualization) |
|---|---|---|
| Ease of implementation | Very easy, everyone knows how | Needs a library or writing scroll calculation logic |
| Performance | Good with < 100 rows, disaster with > 1000 | Always blazing fast, even with 1 million rows |
| Memory (RAM) | Skyrockets with data volume | Always stays stable and low |
| Typing/Scrolling experience | Laggy, delayed | Smooth as silk (60 FPS) |
Juniors often say: "Data will probably never reach 1000 rows". But a Senior always prepares for the worst-case scenario: If data grows to 100,000 rows, will my code still survive?
5. Practical Lesson: "Virtual" but Real
I once saved a Logistic project just by adding react-window to a waybill list. Page load time dropped from 15 seconds to 0.5 seconds. The boss thought I'd performed some incredibly complex magic, but in reality, I just "tricked" the browser with this "optical illusion."
And remember one thing: Virtualization comes with a price in Accessibility and Search (Ctrl + F). Since rows don't actually exist, the browser cannot find them. You have to build your own search mechanism.
The biggest lesson: Never force the browser to do useless work. Don't draw things the user doesn't see. Be calculatedly lazy—that is the peak of performance.
Notes for my 22-year-old self, when I started learning to 'trick' the browser artistically.
Series • Part 15 of 50