tanstack-virtual

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TanStack Virtual

TanStack Virtual

Overview

概述

TanStack Virtual is a headless UI utility for virtualizing large lists, grids, and tables. It renders only the visible items in the viewport, dramatically reducing DOM nodes and improving performance for datasets with thousands of rows. Framework adapters are available for React, Vue, Solid, Svelte, Lit, and Angular.
When to use: Rendering thousands of rows or columns, building virtualized tables, implementing infinite scroll, displaying large datasets where DOM node count impacts performance.
When NOT to use: Small lists under ~100 items (no performance benefit), server-rendered static content, layouts where all items must be in the DOM for SEO or accessibility, simple pagination (render one page at a time instead).
TanStack Virtual 是一款无UI的工具库,用于对大型列表、网格和表格进行虚拟化处理。它仅渲染视口中可见的项目,大幅减少DOM节点数量,提升包含数千行数据的数据集的性能。目前提供了适配React、Vue、Solid、Svelte、Lit和Angular等框架的版本。
适用场景: 渲染数千行或列数据、构建虚拟化表格、实现无限滚动、展示因DOM节点数量影响性能的大型数据集。
不适用场景: 少于约100条数据的小型列表(无性能提升)、服务端渲染的静态内容、所有项目必须在DOM中以满足SEO或无障碍需求的布局、简单分页场景(应改为一次渲染一页数据)。

Quick Reference

快速参考

PatternAPIKey Points
Vertical list
useVirtualizer({ count, getScrollElement, estimateSize })
Wrap items in absolute-positioned container
Horizontal list
useVirtualizer({ horizontal: true, ... })
Use
getTotalSize()
for width instead of height
Grid layoutRow virtualizer + column virtualizerTwo virtualizer instances sharing one scroll element
Dynamic sizing
ref={virtualizer.measureElement}
Set
data-index
on each element
Window scroller
useWindowVirtualizer({ count, estimateSize })
No
getScrollElement
needed
Scroll to item
virtualizer.scrollToIndex(index)
Supports
align: 'start' | 'center' | 'end' | 'auto'
Scroll to offset
virtualizer.scrollToOffset(px)
Supports
align
and
behavior: 'smooth'
Custom keys
getItemKey: (index) => items[index].id
Stable keys improve measurement cache
Overscan
overscan: 5
Renders extra items outside viewport (default: 1)
Gap between items
gap: 8
Space between virtualized items in pixels
Multi-lane layout
lanes: 3
Masonry-style column layouts
Padding
paddingStart: 100, paddingEnd: 100
Space before first and after last item
RTL support
isRtl: true
Right-to-left horizontal scrolling
Disable virtualizer
enabled: false
Renders nothing, resets internal state
Force remeasure
virtualizer.measure()
Call after external layout changes
模式API核心要点
垂直列表
useVirtualizer({ count, getScrollElement, estimateSize })
将项目包裹在绝对定位的容器中
水平列表
useVirtualizer({ horizontal: true, ... })
使用
getTotalSize()
获取宽度而非高度
网格布局行虚拟化器 + 列虚拟化器两个虚拟化器实例共享同一个滚动元素
动态尺寸
ref={virtualizer.measureElement}
为每个元素设置
data-index
属性
窗口滚动器
useWindowVirtualizer({ count, estimateSize })
无需设置
getScrollElement
滚动到指定项
virtualizer.scrollToIndex(index)
支持
align: 'start' | 'center' | 'end' | 'auto'
配置
滚动到指定偏移
virtualizer.scrollToOffset(px)
支持
align
behavior: 'smooth'
配置
自定义键值
getItemKey: (index) => items[index].id
稳定的键值可优化测量缓存
过度渲染
overscan: 5
渲染视口外的额外项目(默认值:1)
项目间距
gap: 8
虚拟化项目之间的间距(单位:像素)
多列布局
lanes: 3
瀑布流样式的列布局
内边距
paddingStart: 100, paddingEnd: 100
第一个项目前和最后一个项目后的间距
RTL支持
isRtl: true
从右到左的水平滚动
禁用虚拟化器
enabled: false
不渲染任何内容,重置内部状态
强制重新测量
virtualizer.measure()
在外部布局变化后调用

Common Mistakes

常见错误

MistakeCorrect Pattern
Missing
overflow: auto
on scroll container
Parent element must have
overflow: auto
and a fixed height/width
Using
virtualItem.index
as React key
Use
virtualItem.key
which accounts for dynamic reordering
Forgetting
position: relative
on inner container
The total-size container must be
position: relative
Not setting
data-index
with
measureElement
Dynamic measurement requires
data-index={virtualItem.index}
on each element
Setting
estimateSize
too small for dynamic items
Overestimate to prevent scroll jumping; use largest expected size
Recreating
getScrollElement
on every render
Use a ref callback:
() => parentRef.current
Not using
getTotalSize()
for container dimensions
Inner container height/width must equal
virtualizer.getTotalSize()
Absolute positioning without
transform
Use
transform: translateY(item.start)
for GPU-accelerated positioning
Using
contain: strict
without fixed dimensions
contain: strict
requires explicit width and height on the scroll container
错误内容正确做法
滚动容器缺少
overflow: auto
属性
父元素必须设置
overflow: auto
并指定固定高度/宽度
使用
virtualItem.index
作为React的key值
使用
virtualItem.key
,它会处理动态重新排序的情况
忘记为内部容器设置
position: relative
总尺寸容器必须设置
position: relative
使用
measureElement
时未设置
data-index
属性
动态测量要求为每个元素设置
data-index={virtualItem.index}
为动态项目设置的
estimateSize
值过小
高估尺寸以防止滚动跳变;使用预期的最大尺寸
每次渲染时重新创建
getScrollElement
函数
使用ref回调:
() => parentRef.current
未使用
getTotalSize()
设置容器尺寸
内部容器的高度/宽度必须等于
virtualizer.getTotalSize()
使用绝对定位但未设置
transform
属性
使用
transform: translateY(item.start)
实现GPU加速定位
在未设置固定尺寸的情况下使用
contain: strict
contain: strict
要求滚动容器设置明确的宽度和高度

Delegation

任务委托

If the
tanstack-table
skill is available, delegate data table virtualization to it. TanStack Table has built-in virtualization integration. Otherwise, recommend:
npx skills add oakoss/agent-skills --skill tanstack-table
If the
tanstack-query
skill is available, delegate data fetching and infinite query patterns to it. Otherwise, recommend:
npx skills add oakoss/agent-skills --skill tanstack-query
如果
tanstack-table
技能可用,将数据表格虚拟化任务委托给它。TanStack Table 内置了虚拟化集成。 否则,推荐执行:
npx skills add oakoss/agent-skills --skill tanstack-table
如果
tanstack-query
技能可用,将数据获取和无限查询模式的任务委托给它。 否则,推荐执行:
npx skills add oakoss/agent-skills --skill tanstack-query

References

参考资料

  • List virtualization with useVirtualizer
  • Grid virtualization with row and column virtualizers
  • Dynamic sizing with measureElement
  • Infinite scroll with TanStack Query integration
  • 使用useVirtualizer实现列表虚拟化
  • 使用行和列虚拟化器实现网格虚拟化
  • 使用measureElement实现动态尺寸
  • 与TanStack Query集成实现无限滚动