All questions

Virtualized List

Premium

Virtualized List

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.

What you'll build

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:

  1. Track the scroll offset. Hold scrollTop in useState(0) and update it from the viewport's onScroll.
  2. Compute the visible window. From scrollTop: start = Math.floor(scrollTop / ROW_H), then a from/to slice padded by an overscan of 3 rows and clamped to [0, TOTAL].
  3. Render only that slice. Map ITEMS.slice(from, to) into rows, offset the window with transform: translateY(from * ROW_H), and update the readout.

Examples

  • At rest the list shows Row #0 … Row #12 and reads rows 0–13 of 10000; the scrollbar is tiny because the spacer is 320,000px tall.
  • Scroll halfway down: scrollTop jumps to ~160000, start becomes ~5000, and the window now renders Row #4997 … Row #5013 — about twenty nodes, never ten thousand.
  • The DOM node count stays roughly constant no matter how far you scroll; only the row contents and the window's translateY change.

Notes

  • Fixed row height is what makes the math cheap. Every row is exactly ROW_H (32px), so the index at any offset is a single division — no per-row measurement.
  • Overscan hides the seams. Rendering a few extra rows above and below the viewport (OVERSCAN = 3) means fast scrolls don't flash blank gaps at the edges.
  • The spacer and the window are separate jobs. The spacer only exists to give the scrollbar its full range; the absolutely-positioned window holds the real rows and is translated into view.

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.

Upgrade to Premium