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

PrimeReact DataTable虚拟滚动懒加载Skeleton预览显示异常求助

PrimeReact DataTable 虚拟滚动懒加载异常问题及解决方案

问题说明

PrimeReact DataTable的虚拟滚动懒加载功能存在异常:官方示例中向下滚动加载时,现有条目会被全部隐藏,仅显示第一组Skeleton加载骨架,不符合「保留当前条目并新增加载模板」的预期。对比之下,PrimeReact原生VirtualScroller组件的懒加载功能是正常的。

目前尝试使用virtualScrollerOptions.appendOnly属性可以避免加载时清空现有内容,但DataTable没有提供类似原生VirtualScroller的onFetchRows事件来精准控制加载状态UI。我曾考虑在lazyLoad触发时,通过isLoading标记手动向数据列表添加带加载模板的记录,加载完成后切换标记并替换为真实数据,但不确定这个思路是否正确。

问题分析

DataTable的虚拟滚动懒加载逻辑对原生VirtualScroller做了封装,当前实现触发lazyLoad时会直接重置数据集并替换为加载骨架,而非在现有数据基础上追加加载状态的内容。appendOnly模式虽然能保留已有数据,但缺少配套事件来触发加载状态的UI更新,导致无法直接实现「保留旧数据+显示底部加载骨架」的效果。

可行解决方案

手动维护加载状态占位记录的思路是可行的,具体实现步骤如下:

  1. 状态管理:维护data数据集、isLoading加载状态、totalRecords总记录数三个核心状态
  2. 触发加载时添加占位:调用lazyLoad时,将isLoading设为true,同时向data末尾添加一条标记为加载状态的占位记录
  3. 加载完成后替换占位:异步获取数据完成后,将isLoading设为false,移除占位记录并将新数据追加到data中
  4. 列模板区分渲染:在列的body模板中,根据记录的加载状态渲染Skeleton或正常内容

代码示例

import { useState } from 'react';
import { DataTable, LazyLoadEvent, Skeleton } from 'primereact';

// 模拟数据获取函数
const fetchNewData = (first: number, rows: number) => {
  return Array.from({ length: rows }, (_, i) => ({
    id: first + i + 1,
    name: `Item ${first + i + 1}`
  }));
};

const LazyVirtualScrollTable = () => {
  const [data, setData] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [totalRecords, setTotalRecords] = useState(100);

  const lazyLoad = (event: LazyLoadEvent) => {
    setIsLoading(true);
    // 添加加载占位记录
    setData(prev => [...prev, { isLoading: true }]);

    // 模拟异步请求
    setTimeout(() => {
      const newData = fetchNewData(event.first!, event.rows!);
      setIsLoading(false);
      // 移除占位记录并追加新数据
      setData(prev => prev.filter(item => !item.isLoading).concat(newData));
    }, 1000);
  };

  const columns = [
    {
      field: 'id',
      header: 'ID',
      body: (rowData: any) => rowData.isLoading ? <Skeleton /> : rowData.id
    },
    {
      field: 'name',
      header: 'Name',
      body: (rowData: any) => rowData.isLoading ? <Skeleton /> : rowData.name
    }
  ];

  return (
    <DataTable
      value={data}
      lazy
      onLazyLoad={lazyLoad}
      totalRecords={totalRecords}
      scrollable
      scrollHeight="500px"
      virtualScrollerOptions={{ appendOnly: true }}
      columns={columns}
    />
  );
};

export default LazyVirtualScrollTable;

补充说明

  • 开启virtualScrollerOptions.appendOnly是关键,它能阻止DataTable在加载时重置现有数据列表
  • 占位记录的标记字段(如isLoading)需要和真实数据字段区分开,避免冲突
  • 若需要更精准的加载位置控制(比如只在底部显示一个加载骨架),可以调整占位记录的数量,或者单独在表格底部渲染Skeleton组件,通过isLoading控制显示/隐藏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:57:33