You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TanStack react-table v8中集成react-virtual(v3 beta版)

TanStack React-Table v8 集成 React-Virtual v3.x 实现行虚拟化

针对你的需求,我调整了代码实现两个库的集成,完整代码如下:

import type { ReactElement } from "react";
import { useRef, useEffect } from "react";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeaderCell,
  TableRow,
} from "./style";
import {
  flexRender,
  getCoreRowModel,
  useReactTable,
} from "@tanstack/react-table";
import type { ColumnDef } from "@tanstack/react-table";
import { useVirtualizer } from "@tanstack/react-virtual";

interface TableProps {
  columns: Array<ColumnDef<any, string>>;
  data: any;
  rowHeight?: number; // 可选,自定义行高
}

function CustomTable(props: TableProps): ReactElement {
  const { columns, data, rowHeight = 48 } = props;
  const tableContainerRef = useRef<HTMLDivElement>(null);
  const tableBodyRef = useRef<HTMLTableSectionElement>(null);

  const tableInstance = useReactTable({
    columns,
    data,
    getCoreRowModel: getCoreRowModel(),
  });

  const rowVirtualizer = useVirtualizer({
    count: tableInstance.getRowModel().rows.length,
    getScrollElement: () => tableContainerRef.current,
    estimateSize: () => rowHeight,
    // 当虚拟列表更新时同步表格体高度
    onChange: () => {
      if (tableBodyRef.current) {
        tableBodyRef.current.style.height = `${rowVirtualizer.getTotalSize()}px`;
      }
    },
  });

  // 表格数据变化时更新虚拟列表计数
  useEffect(() => {
    rowVirtualizer.setCount(tableInstance.getRowModel().rows.length);
  }, [tableInstance.getRowModel().rows.length, rowVirtualizer]);

  return (
    <div
      ref={tableContainerRef}
      style={{
        height: "500px", // 可根据需求调整容器高度
        overflow: "auto",
      }}
    >
      <Table style={{ width: "100%", borderCollapse: "collapse" }}>
        <TableHead>
          {tableInstance.getHeaderGroups().map(headerGroup => {
            return (
              <TableRow key={headerGroup.id}>
                {headerGroup.headers.map(header => {
                  return (
                    <TableHeaderCell key={header.id}>
                      <span>
                        {header.isPlaceholder
                          ? null
                          : flexRender(
                              header.column.columnDef.header,
                              header.getContext()
                            )}
                      </span>
                    </TableHeaderCell>
                  );
                })}
              </TableRow>
            );
          })}
        </TableHead>
        <TableBody ref={tableBodyRef} style={{ position: "relative" }}>
          {/* 占位元素:撑开表格体高度,保证滚动范围正确 */}
          <div
            style={{
              height: `${rowVirtualizer.getTotalSize()}px`,
              position: "absolute",
              top: 0,
              left: 0,
              right: 0,
              pointerEvents: "none",
            }}
          />
          {/* 仅渲染视口内可见的行 */}
          {rowVirtualizer.getVirtualItems().map(virtualItem => {
            const row = tableInstance.getRowModel().rows[virtualItem.index];
            return (
              <TableRow
                $border
                key={row.id}
                style={{
                  position: "absolute",
                  top: 0,
                  left: 0,
                  right: 0,
                  transform: `translateY(${virtualItem.start}px)`,
                }}
              >
                {row.getVisibleCells().map(cell => {
                  return (
                    <TableCell key={cell.id}>
                      <span>
                        {flexRender(
                          cell.column.columnDef.cell,
                          cell.getContext()
                        )}
                      </span>
                    </TableCell>
                  );
                })}
              </TableRow>
            );
          })}
        </TableBody>
      </Table>
    </div>
  );
}

export default CustomTable;

关键改动说明

  • 滚动容器调整:把滚动容器改为外层div,设置固定高度和滚动属性,确保react-virtual能正确捕获滚动事件。
  • 虚拟行渲染逻辑:不再全量渲染所有行,而是通过rowVirtualizer.getVirtualItems()获取视口内可见的行,用绝对定位和transform将行放到正确位置。
  • 滚动范围保证:添加占位元素,用虚拟列表的总高度撑开表格体,确保容器滚动条的范围正确。
  • 数据同步处理:监听表格行数量变化,同步更新虚拟列表的计数,避免数据更新后虚拟列表不生效。
  • 行高灵活配置:新增rowHeight参数,默认48px,替换原有的15px估算值,提升虚拟列表的定位准确性。

内容的提问来源于stack exchange,提问作者Oren Papa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 19:22:52