当前位置: 首页 > news >正文

react Antd Table 多选大数据量 UI渲染很慢的解决方案

问题: react 在选择大量的数据后,继续点击页面的选中会出现UI渲染很慢的情况
在这里插入图片描述

完全将 UI 隔离的方案
代码:


import { Table, Button, Space, Tag } from 'antd';
import React, { useState, useEffect, useRef, useCallback } from 'react';/*** 模拟 API 请求模块* @param {object} params - 请求参数,包含 page 和 pageSize* @returns {Promise<{records: object[], total: number}>}*/
const mockApi = {fetchList: ({ page, pageSize }) => {console.log(`Fetching data for page: ${page}, pageSize: ${pageSize}`);return new Promise((resolve) => {const totalRecords = 50000; // 模拟一个非常大的数据集const start = (page - 1) * pageSize;// 生成当前页的模拟数据const records = Array.from({ length: pageSize }, (_, i) => {const index = start + i;if (index >= totalRecords) return null; // 避免超出总数return {baseId: `id_${index + 1}`, // 保证 key 的唯一性name: `项目 ${index + 1}`,category: ['A', 'B', 'C'][index % 3],status: ['Active', 'Inactive', 'Archived'][index % 3],};}).filter(Boolean); // 过滤掉 null 值// 模拟网络延迟setTimeout(() => {resolve({ records, total: totalRecords });}, 300);});},
};/*** 高性能跨页选择表格组件*/
function HighPerformanceSelectableTable() {const [loading, setLoading] = useState(false);const [dataSource, setDataSource] = useState([]); // State: 仅存储当前页的表格数据const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 });// 核心 State 1: 存储所有页面已选中的 key,使用 Set 数据结构以获得最佳性能const [allSelectedRowKeys, setAllSelectedRowKeys] = useState(new Set());// 核心 State 2: 仅存储当前页已选中的 key,直接用于驱动 Table UI,保证 UI 响应速度const [currentPageSelectedRowKeys, setCurrentPageSelectedRowKeys] = useState([]);// 核心 Ref: 数据缓存。使用 useRef 创建一个在组件生命周期内持久的 Map 对象// 用于存储所有已加载的数据,且其变化不会触发组件重新渲染const dataCache = useRef(new Map());// 表格列定义const columns = [{ title: '项目 ID', dataIndex: 'baseId', width: 200 },{ title: '项目名称', dataIndex: 'name', width: 250 },{ title: '分类', dataIndex: 'category', width: 150 },{title: '状态',dataIndex: 'status',render: (status) => <Tag color={status === 'Active' ? 'green' : 'red'}>{status}</Tag>,},];// 数据获取函数,使用 useCallback 避免不必要的函数重建const fetchData = useCallback(async (params) => {setLoading(true);const result = await mockApi.fetchList({page: params.current,pageSize: params.pageSize,});setLoading(false);if (result && result.records) {setDataSource(result.records);setPagination((prev) => ({ ...prev, ...params, total: result.total }));// 将新获取的数据存入缓存,以便后续根据 key 能找到完整的 row 数据result.records.forEach((item) => {dataCache.current.set(item.baseId, item);});}}, []);// 首次加载数据useEffect(() => {fetchData({ current: 1, pageSize: 10 });}, [fetchData]);// 处理分页、排序、筛选变化const handleTableChange = (newPagination) => {fetchData({ current: newPagination.current, pageSize: newPagination.pageSize });};// 【关键同步逻辑】// 当 `dataSource` (翻页) 或 `allSelectedRowKeys` (外部操作) 变化时,// 需要重新计算当前页应该展示的勾选状态。useEffect(() => {const keysToShowOnCurrentPage = dataSource.map((item) => item.baseId).filter((key) => allSelectedRowKeys.has(key));setCurrentPageSelectedRowKeys(keysToShowOnCurrentPage);}, [dataSource, allSelectedRowKeys]);// 【核心选择逻辑】// 当用户在表格中进行勾选操作时触发const handleRowSelectionChange = (selectedKeysOnCurrentPage) => {// 步骤 1: 立刻更新当前页的 UI State,确保勾选框的即时响应setCurrentPageSelectedRowKeys(selectedKeysOnCurrentPage);// 步骤 2: 异步更新全局的已选 key 集合 (Set)setAllSelectedRowKeys((prevAllKeys) => {const newAllKeys = new Set(prevAllKeys); // 复制一份,保证 state 的不可变性const currentPageKeys = dataSource.map((item) => item.baseId);// 遍历当前页的所有 keycurrentPageKeys.forEach((key) => {// 如果这个 key 在当前页的最新选中项里,就添加到全局 Set 中if (selectedKeysOnCurrentPage.includes(key)) {newAllKeys.add(key);} else {// 否则(即未选中或被取消选中),就从全局 Set 中移除newAllKeys.delete(key);}});return newAllKeys;});};// Table 的 rowSelection prop 配置const rowSelection = {selectedRowKeys: currentPageSelectedRowKeys, // **关键**: 只将当前页的选中 keys 传给 TableonChange: handleRowSelectionChange,// (可选) 增加 getCheckboxProps 来自定义禁用逻辑// getCheckboxProps: (record) => ({//   disabled: record.status === 'Archived',// }),};// 点击按钮获取所有选中项const showAllSelected = () => {// 从 Set 转换为数组const allKeysArray = Array.from(allSelectedRowKeys);// 从缓存中根据 key 查找完整的行数据const allSelectedRows = allKeysArray.map((key) => dataCache.current.get(key)).filter(Boolean);console.group('所有选中项详情');console.log('总数:', allSelectedRows.length);console.log('所有选中的 Keys:', allKeysArray);console.log('所有选中的 Rows:', allSelectedRows);console.groupEnd();// alert(`已选择 ${allSelectedRows.length} 条记录,详情请查看控制台。`);};// 清空所有选择const clearAllSelection = () => {setAllSelectedRowKeys(new Set());// currentPageSelectedRowKeys 会通过 useEffect 自动同步变为空数组};return (<div style={{ padding: '20px' }}><Space direction="vertical" style={{ width: '100%' }}><Space><Button type="primary" onClick={showAllSelected} disabled={allSelectedRowKeys.size === 0}>获取所有选中项</Button><Button onClick={clearAllSelection} disabled={allSelectedRowKeys.size === 0}>清空所有选择</Button></Space><div style={{ fontWeight: 'bold' }}>总共已选择 <Tag color="blue">{allSelectedRowKeys.size}</Tag></div><Tablesize="middle"rowKey="baseId"loading={loading}columns={columns}dataSource={dataSource}rowSelection={rowSelection}pagination={pagination}onChange={handleTableChange}borderedscroll={{y: 'calc(100vh - 615px)',}}/></Space></div>);
}export default HighPerformanceSelectableTable;
http://www.dtcms.com/a/355528.html

相关文章:

  • 每日五个pyecharts可视化图表日历图和箱线图:从入门到精通
  • ChatGPT登录,拒绝访问,错误1020解决办法
  • THM Whats Your Name WP
  • QT .pro文件的常见用法
  • 与trae携手,构建owtb一体化物流平台之--需求文档V0.3
  • RTL8198E SDK温控机制
  • 家电公司跨界造车,追觅能否造出“电动时代的布加迪”
  • 【架构师干货】软件工程
  • 从卡顿到丝滑:大型前端项目 CSS 优化全攻略
  • Agent实战教程:Langgraph的StateGraph以及State怎么用
  • 如何安装InfluxDB 1.7.0 Windows版(influxdb-1.7.0_windows_amd64.exe使用方法附安装包下载)​
  • 群晖 DS225+ 和绿联 DXP2800:企业文件备份方案对比
  • 仿生纺织飞行模块专利拆解:螺旋旋转结构的空气动力学与升力产生机制
  • curl打印信息实现
  • 如何将yolo训练图像数据库的某个分类的图像取出来
  • Step-by-Step: 接入淘宝商品详情 API 并解析返回数据
  • 无人机+AI光伏热斑检测技术
  • 大模型训练中对SFT和DPO的魔改——PROXIMAL SUPERVISED FINE-TUNING和Semi-online DPO论文阅读笔记
  • 锁的种类都有什么
  • Vue3 + Rsbuild 完全指南:10倍构建速度的现代前端开发方案
  • 解锁AI“黑匣”:监督、无监督与强化学习探秘
  • 某供应链金融公司多场景敏感数据安全保护实践
  • AI智能金融风控新实践:从信贷秒批到支付防护,筑牢金融安全新屏障
  • 实战经验-无mac电脑上传ipa到appstore构建版本
  • 图论好题推荐-逛公园
  • 【论文阅读】多功能肌电控制的新策略
  • Magnet Pro Macbook窗口分屏管理(Mac窗口分屏)
  • 安宝特方案丨AR异地专家远程支持平台,适合:机电运维、应急处置、监造验收
  • 光谱相机在雾霾监测中有何优势?
  • 测试题ansible临时命令模块