useVirtualList
Free · MITRender only the items of a long list that are in or near view, for Thread's and SessionList's virtualize. Items keep their measured heights by key, so a list that grows or reorders keeps its place; unmeasured items count as estimate. Spacers stand in for the rest. pin (an item's key) keeps that item rendered (the one holding focus), on its own if it's far from view, so focus is never lost to an item scrolling away. Until the scroller is measured (on the server, on the first render in the browser, and while it's hidden) the first or last initial items render, by anchor, so server and browser agree.
Give each rendered item ref={list.measure} and data-virtual-key={key}.
Preview
It's types and helpers, listed below.
Install
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/use-virtual-list
Functions
useVirtualList({ enabled, count, keyOf, scroller, estimate = 96, overscan = 800, initial = 20, anchor = "end", gap = () => 0, pin, }: { enabled: boolean count: number keyOf: (index: number) => React.Key scroller: React.RefObject<HTMLElement | null> estimate?: number | undefined overscan?: number | uRender only the items of a long list that are in or near view, for Thread's and SessionList's virtualize. Items keep their measured heights by key, so a list that grows or reorders keeps its place; unmeasured items count as estimate. Spacers stand in for the rest. pin (an item's key) keeps that item rendered (the one holding focus), on its own if it's far from view, so focus is never lost to an item scrolling away. Until the scroller is measured (on the server, on the first render in the browser, and while it's hidden) the first or last initial items render, by anchor, so server and browser agree.
Give each rendered item ref={list.measure} and data-virtual-key={key}.
Types
- VirtualRow
- What to render, in order: an item by its index, or a spacer standing in for the items between.
{ index: number } | { spacer: number; key: string }- VirtualList
{ /** The items to render and the spacers between them, in order. */ rows: VirtualRow[] /** The ref for every rendered item, which also carries `data-virtual-key={key}`, so its real height is measured and kept. */ measure: (el: HTMLElement | null) => void | (() => void) }