React cookbook · Intermediate
Render 10,000 rows smoothly with virtualization
Display a very long list or table without freezing the browser.
Approach
Render only the visible rows using TanStack Virtual: a scroll container with a fixed height, an inner element sized to the total height, and absolutely positioned rows for the virtual items. Use measureElement for variable row heights.
Solution
import { useRef } from "react";
import { useVirtualizer } from "@tanstack/react-virtual";
export function LogList({ rows }: { rows: LogLine[] }) {
const parentRef = useRef<HTMLDivElement>(null);
const virtualizer = useVirtualizer({
count: rows.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 32,
overscan: 10,
});
return (
<div ref={parentRef} style={{ height: 600, overflow: "auto" }} role="list" aria-label="Log lines">
<div style={{ height: virtualizer.getTotalSize(), position: "relative" }}>
{virtualizer.getVirtualItems().map((item) => {
const row = rows[item.index];
return (
<div
key={row.id}
role="listitem"
data-index={item.index}
ref={virtualizer.measureElement}
style={{ position: "absolute", top: 0, left: 0, width: "100%", transform: `translateY(${item.start}px)` }}
>
<time>{row.time}</time> {row.message}
</div>
);
})}
</div>
</div>
);
}
Pitfalls
- Virtualizing short lists (complexity without benefit).
- Breaking Ctrl+F search and screen reader navigation — consider pagination for content users need to search.
- Using index keys when rows can be inserted.
Variations
- Combine with
useInfiniteQueryto load more as the user scrolls. - TanStack Table + Virtual for large data grids.
Further reading: TanStack Virtual
Reference: https://tanstack.com/virtual/latest/docs/introduction
More React recipes
- Add optimistic updates to a todo list
- Build an accessible modal dialog
- Build infinite scroll with TanStack Query
- Call a cookie-authenticated API with CSRF protection
- Debounce a search input in React
- Handle errors gracefully with error boundaries
- Implement dark mode that follows the system
- Poll a long-running job's status