跪拜 Guibai
← All articles
Frontend · JavaScript · Interview

AI-Generated Virtual Lists White-Screen Under Fast Scroll — Here's the Fix

By kyriewen ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

A virtual list that blanks under fast scroll is a production outage disguised as a minor UI glitch. Knowing that overscan, transform-based positioning, and rAF-throttled scroll handlers are what prevent it separates a candidate who can debug a real user-facing bug from one who can only prompt an LLM.

Summary

An AI-written virtual list renders correctly at slow speeds but produces a white screen when the scrollbar is dragged quickly. The root cause is the gap between synchronous browser scrolling and React's asynchronous re-render: old DOM nodes scroll out of view before new ones mount. The fix is overscan — rendering a handful of extra rows above and below the visible window so the browser always has content to paint during rapid scrolls. The change requires only three lines of code to expand the start and end index calculations by a buffer count.

Beyond the white-screen fix, six follow-up questions unpack deeper virtual-list mechanics: why transform beats padding-top for positioning (compositing vs. layout reflow), how to handle variable row heights with estimated measurements and post-render correction, why requestAnimationFrame throttles scroll events better than setTimeout, the danger of using loop indices as React keys in a shifting window, and the performance crossover point where virtual lists beat time-slicing at roughly 5,000 rows. Each answer ties directly to a production failure mode that a library like TanStack Virtual papers over — until it doesn't.

Takeaways
AI-generated virtual lists white-screen during fast scrolling because onScroll fires asynchronously and React hasn't mounted the new visible rows yet.
Adding an overscan buffer of 5–10 rows above and below the viewport keeps extra DOM nodes ready, eliminating the flash.
Using transform: translateY() for offset avoids layout reflow; padding-top triggers a full Layout recalculation and can cause a 5–10x frame-rate drop on large lists.
Variable row heights require an estimated-height map that gets corrected with getBoundingClientRect after each row renders.
Throttling onScroll with requestAnimationFrame aligns state updates to the browser's refresh frames, preventing jank that setTimeout-based throttling can introduce.
React keys in a virtual list must use the data's unique ID or the absolute row index; reusing a loop index causes React to recycle DOM nodes with stale content.
Virtual lists outperform time-slicing above roughly 5,000 rows because time-slicing eventually mounts every DOM node, consuming 200MB+ of memory for 100,000 rows.
TanStack Virtual handles overscan, dynamic heights, and infinite loading in production, but understanding the internals is what lets you debug it when it misbehaves.
Conclusions

The white-screen failure is a direct consequence of treating onScroll as synchronous when React's setState batching introduces a render delay — a timing bug that AI code generators routinely miss because they optimize for logical correctness, not frame-level behavior.

Overscan is a one-line fix that transforms a virtual list from a demo into something production-usable, yet it's absent from most tutorial implementations and AI-generated snippets.

The transform-vs-paddingTop distinction is a litmus test for whether a frontend engineer understands the browser rendering pipeline beyond the React abstraction layer.

Interviewers are increasingly using AI-generated code as a baseline and probing whether the candidate can diagnose its failure modes — the skill being tested is debugging reasoning, not syntax recall.

Concepts & terms
Overscan (virtual list buffer)
Rendering a small number of extra list items above and below the visible viewport so that fast scrolling always finds DOM nodes ready to paint, preventing white flashes caused by the render lag between scroll events and React re-renders.
Compositing vs. Layout (transform vs. padding-top)
CSS transform operates at the compositing stage of the browser rendering pipeline, moving a GPU layer without triggering Layout or Paint. Padding-top forces a full Layout reflow, which is far more expensive and can drop frame rates by 5–10x during rapid scrolling.
requestAnimationFrame throttling
A technique that limits scroll-handler state updates to once per browser refresh frame by scheduling setState inside a rAF callback, ensuring renders stay synchronized with the display refresh rate and avoiding the jank caused by timer-based throttling.
Dynamic row height measurement
A pattern for virtual lists with variable item heights: maintain a map of measured heights, use an estimated height for unrendered rows, and update the map with getBoundingClientRect after each row mounts so subsequent offset calculations use real dimensions.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗