All questions

Virtualized List

Premium

Virtualized List

Build a fixed-height virtual list for 10,000 activity records. The scrollbar must represent the whole dataset, while React mounts only the visible slice plus a small overscan buffer.

What you'll build

The polished starter renders the complete resting view and its 440,000px spacer, but the first slice stays pinned when you scroll. Add React state, an onScroll handler, and render-time derivations.

  1. Store scrollTop with useState(0) and update it from event.currentTarget.scrollTop.
  2. Derive start, from, to, offset, and visible on every render. Do not store the slice separately.
  3. Translate the window by from * ROW_HEIGHT, render only ITEMS.slice(from, to), and keep both footer counts in sync.

Behavior contract

  • Constants are exact: TOTAL = 10000, ROW_HEIGHT = 44, VIEWPORT_HEIGHT = 352, and OVERSCAN = 3.
  • Compute start = floor(scrollTop / ROW_HEIGHT), from = max(0, start - OVERSCAN), and to = min(TOTAL, start + ceil(VIEWPORT_HEIGHT / ROW_HEIGHT) + OVERSCAN).
  • At rest render items 1–11, show Showing 1–11 of 10,000, and show 11 row nodes. At scrollTop = 4400, render items 98–111 and translate the window to 4268px.
  • The spacer height is 440,000px. The DOM contains only the current slice and never all 10,000 rows.
  • Preserve the supplied interface and accessibility: the focusable viewport is role="list"; rows are role="listitem" with aria-setsize="10000" and one-based aria-posinset; the readout is a polite status.

Notes

  • Fixed height makes index lookup constant-time; variable-height rows need measurements and an offset index.
  • Overscan hides blank seams during fast scrolling. Clamp both boundaries before slicing.
  • Use stable item ids as React keys. Styling remains in styles.css when the solution replaces App.tsx.
WE’RE LISTENING

Help make UIReady better

Found a bug or have an idea? Tell us about it.

Up to 3 files · 5 MiB each · JPG, PNG, WebP, MP4, WebM, MP3, M4A or WAV