Render a scrollable list of 10,000 rows without putting 10,000 nodes in the DOM. The trick — called windowing or virtualization — is to keep the scrollbar honest with one tall spacer while only rendering the handful of rows that are actually inside the viewport. As the user scrolls, you recompute which slice is visible and move it into place. This is what libraries like react-window do under the hood.
The starter App.tsx renders the viewport already showing the first window of rows (rows 0–13) inside a 320,000px-tall spacer, with the readout rows 0–13 of 10000. There is no scroll logic yet. Make it live:
scrollTop in useState(0) and update it from the viewport's onScroll.scrollTop: start = Math.floor(scrollTop / ROW_H), then a from/to slice padded by an overscan of 3 rows and clamped to [0, TOTAL].ITEMS.slice(from, to) into rows, offset the window with transform: translateY(from * ROW_H), and update the readout.Row #0 … Row #12 and reads rows 0–13 of 10000; the scrollbar is tiny because the spacer is 320,000px tall.scrollTop jumps to ~160000, start becomes ~5000, and the window now renders Row #4997 … Row #5013 — about twenty nodes, never ten thousand.translateY change.ROW_H (32px), so the index at any offset is a single division — no per-row measurement.OVERSCAN = 3) means fast scrolls don't flash blank gaps at the edges.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.