#VirtualList
Browse large lists smoothly.
#Basic usage
- Item 1
- Item 2
- Item 3
- Item 4
- Item 5
- Item 6
- Item 7
- Item 8
- Item 9
- Item 10
- Item 11
import { VirtualList } from '@ifhover/leaf-ui';
import { useState } from 'react';
export function VirtualListBasic() {
const [items] = useState(() =>
Array.from({ length: 10000 }, (_, index) => ({
id: String(index),
name: `Item ${index + 1}`,
})),
);
return (
<VirtualList
items={items}
itemKey={(item) => item.id}
height={240}
estimateSize={44}
renderItem={(item) => <div style={{ padding: '12px 16px' }}>{item.name}</div>}
/>
);
}
#More examples
- #0
Content with varying length.
- #1
Content with varying length. Content with varying length.
- #2
Content with varying length. Content with varying length. Content with varying length.
- #3
Content with varying length.
- #4
Content with varying length. Content with varying length.
- #5
Content with varying length. Content with varying length. Content with varying length.
- #6
Content with varying length.
- #7
Content with varying length. Content with varying length.
- #8
Content with varying length. Content with varying length. Content with varying length.
import { Button, Space, VirtualList } from '@ifhover/leaf-ui';
import { useRef, useState } from 'react';
export function VirtualListDynamic() {
const list = useRef<import('@ifhover/leaf-ui').VirtualListHandle>(null);
const [items] = useState(() =>
Array.from({ length: 1000 }, (_, index) => ({
id: String(index),
text: 'Content with varying length. '.repeat((index % 3) + 1),
})),
);
return (
<Space direction="vertical" align="stretch">
<Button variant="outline" onClick={() => list.current?.scrollToIndex(500, 'start')}>
Go to item 501
</Button>
<VirtualList
ref={list}
items={items}
itemKey={(item) => item.id}
height={220}
estimateSize={60}
renderItem={(item) => (
<div style={{ padding: 16 }}>
<strong>#{item.id}</strong>
<p style={{ margin: '4px 0' }}>{item.text}</p>
</div>
)}
/>
</Space>
);
}
#Usage
Keep itemKey stable. estimateSize is used initially; rows are measured afterward. SSR outputs a deterministic initial window that adjusts after mounting.
#Types
Import these types for data, callbacks and refs.
import type { VirtualListHandle, VirtualListProps } from '@ifhover/leaf-ui';#VirtualListHandle API
| Property | Type | Default | Description |
|---|---|---|---|
element | HTMLDivElement | null | Required | Scroll container element |
scrollToIndex | (index: number, align?: 'auto' | 'start' | 'center' | 'end') => void | Required | Scroll to an item |
scrollToOffset | (offset: number) => void | Required | Scroll to an offset |
#VirtualListProps API
| Property | Type | Default | Description |
|---|---|---|---|
items | readonly T[] | Required | Items; keep keys unique and stable |
itemKey | (item: T, index: number) => Key | Required | Return a stable identifier |
renderItem | (item: T, index: number) => ReactNode | Required | Custom item renderer |
height | number | 320 | Height, numbers are in pixels |
estimateSize | number | ((item: T, index: number) => number) | 40 | Estimated item size; actual size is measured |
overscan | number | 5 | Items rendered outside the visible range |
emptyContent | ReactNode | — | Empty list content |
horizontal | boolean | false | Horizontal virtual list |