React Radix UI Table结合Virtuoso虚拟渲染样式异常与报错问题
解决Radix UI Themes Table结合react-virtuoso虚拟滚动的样式错乱与DOM结构报错问题
问题根源
<div> cannot appear as a child of <tbody>:TableVirtuoso默认会生成一个<div>容器作为列表外层,而HTML规范中<tbody>的直接子元素只能是<tr>,导致DOM结构非法。<tr> cannot appear as a child of <tr>:默认渲染逻辑下,Virtuoso会额外嵌套行容器,和Radix的<Table.Row>产生嵌套冲突。
解决方案代码
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'; import { Table } from "@radix-ui/themes" import { useRef } from "react" import { TableVirtuoso } from 'react-virtuoso'; const TableScrollArea = () => { const scrollViewportRef = useRef(null); // 生成10000条模拟数据 const dataArray = Array.from({ length: 10000 }, () => ({ name: 'AAA', email: 'AAA', title: 'AAA', })); const TableRow = ({ person, index }) => { return ( <Table.Row key={`row-${index}`}> <Table.RowHeaderCell>{person.name}</Table.RowHeaderCell> <Table.Cell>{person.email}</Table.Cell> <Table.Cell>{person.title}</Table.Cell> </Table.Row> ) } return ( <div className="w-full"> {/* 固定表头(可选,若不需要固定可合并到滚动容器内) */} <Table.Root> <Table.Header> <Table.Row> <Table.ColumnHeaderCell>Full name</Table.ColumnHeaderCell> <Table.ColumnHeaderCell>Email</Table.ColumnHeaderCell> <Table.ColumnHeaderCell>Group</Table.ColumnHeaderCell> </Table.Row> </Table.Header> </Table.Root> {/* 虚拟滚动的表体区域 */} <ScrollAreaPrimitive.Root className="h-[300px]"> <ScrollAreaPrimitive.Viewport ref={scrollViewportRef} className="h-full"> <Table.Root> <TableVirtuoso data={dataArray} // 自定义组件结构,适配Radix Table的DOM规范 components={{ TableBody: ({ children }) => <Table.Body>{children}</Table.Body>, Item: ({ children }) => children }} itemContent={(index, person) => <TableRow person={person} index={index} />} customScrollParent={scrollViewportRef.current} // 预估行高,提升虚拟滚动计算精度 estimatedItemSize={48} /> </Table.Root> </ScrollAreaPrimitive.Viewport> <ScrollAreaPrimitive.Scrollbar orientation="vertical"> <ScrollAreaPrimitive.Thumb /> </ScrollAreaPrimitive.Scrollbar> </ScrollAreaPrimitive.Root> </div> ) }; export default TableScrollArea
关键修改说明
自定义Virtuoso组件结构
通过components属性替换默认容器:TableBody指定为Radix的<Table.Body>,避免生成多余divItem直接返回子元素,消除tr嵌套tr的问题
滚动容器引用优化
使用useRef替代useState获取滚动容器,避免状态更新触发不必要的重渲染固定表头拆分
将表头单独抽离到滚动容器外,实现表头固定效果(不需要的话可合并到滚动区域内)行高预估与唯一Key
设置estimatedItemSize帮助Virtuoso更精准计算可视范围;给每行添加唯一Key,避免React渲染警告
修改后即可符合HTML DOM规范,解决报错同时保留Radix Table的原有样式,实现大量数据的流畅虚拟滚动。
内容的提问来源于stack exchange,提问作者Rolando
相关产品推荐
相关产品推荐

