用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill tanstack-virtual命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | tanstack-virtual |
| description | | Use when this capability is needed. |
npm install @tanstack/react-virtual
Three required options — everything else is optional:
count — total item count
getScrollElement — () => scrollableElement
estimateSize — (index) => number (px)
You must:
getTotalSize()virtualItem.startimport { useRef } from 'react'
import { useVirtualizer } from '@tanstack/react-virtual'
function List({ items }: { items: string[] }) {
const parentRef = useRef<HTMLDivElement>(null)
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 35,
})
return (
<div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>
<div style={{ height: `${virtualizer.getTotalSize()}px`, position: 'relative' }}>
{virtualizer.getVirtualItems().map((item) => (
<div
key={item.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${item.size}px`,
transform: `translateY(${item.start}px)`,
}}
>
{items[item.index]}
</div>
))}
</div>
</div>
)
}
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 100, // err large for better scroll-to-index accuracy
})
{virtualizer.getVirtualItems().map((item) => (
<div
key={item.key}
data-index={item.index} // required for measureElement
ref={virtualizer.measureElement} // measures on mount/resize
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
transform: `translateY(${item.start}px)`,
// Do NOT set height — virtualizer controls it
}}
>
{items[item.index]}
</div>
))}
import { useRef, useEffect } from 'react'
import { useWindowVirtualizer } from '@tanstack/react-virtual'
function WindowList({ items }: { items: string[] }) {
const listRef = useRef<HTMLDivElement>(null)
const virtualizer = useWindowVirtualizer({
count: items.length,
estimateSize: () => 35,
scrollMargin: listRef.current?.offsetTop ?? 0,
})
return (
<div ref={listRef}>
<div style={{ height: `${virtualizer.getTotalSize()}px`, position: 'relative' }}>
{virtualizer.getVirtualItems().map((item) => (
<div
key={item.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${}`,
`(${ })`,
}}
>
{items[item.index]}
))}
)
}
scrollMargin = distance from page top to list top. Subtract it from item.start in the transform.
virtualizer.scrollToIndex(50, { align: 'start' }) // 'start' | 'center' | 'end' | 'auto'
virtualizer.scrollToOffset(1200, { behavior: 'smooth' })
Always:
overflow: auto on scroll containerheight/width on scroll containerposition: relative on inner container sized to getTotalSize()position: absolute on each virtual itemtranslateY/translateX for positioning (not top/left)data-index on items when using measureElementitem.key as React key (not item.index)scrollMargin for window virtualizers when content precedes the listNever:
height on dynamically measured itemsoverflow: auto on scroll containersmooth scroll behavior with dynamic-size items (documented limitation)| Option | Default | Purpose |
|---|---|---|
overscan | 1 | Extra items rendered outside visible area |
gap | 0 | Spacing between items (px) — use instead of CSS margin |
paddingStart | 0 | Padding before first item (px) |
paddingEnd | 0 | Padding after last item (px) |
horizontal | false | Horizontal orientation |
lanes | 1 | Columns (vertical) or rows (horizontal) for masonry |
getItemKey | index | Stable item keys — always set when items have IDs |
enabled | true | Set false to disable observers and reset state |
isRtl | false | RTL horizontal scroll |
Converted and distributed by TomeVault — claim your Tome and manage your conversions.