React useEffect处理大数据表格:平滑过渡的最佳实践
React 17.0.2 大数据表格渲染最佳实践
针对大数据表格渲染卡顿的问题,场景二中的延迟加载只是临时缓解方案,更彻底的优化可以从以下几个方向入手:
1. 开启虚拟滚动(最核心的优化)
Material React Table内置了虚拟滚动支持,开启后只会渲染当前可视区域内的行,直接减少DOM节点数量,从根源解决卡顿问题。
const [tableData, setTableData] = useState([]); useEffect(() => { setTableData([...largeData]); }, []); return ( <MaterialReactTable columns={columnsList} data={tableData} enableVirtualization // 启用虚拟滚动 virtualizerProps={{ overscan: 5, // 预渲染可视区域上下各5行,提升滚动流畅度 }} /> );
2. 渐进式数据加载(分批渲染)
不要一次性加载所有数据,而是分批次逐步追加,让浏览器有时间处理UI渲染:
const [tableData, setTableData] = useState([]); const batchSize = 100; // 每次加载100条 useEffect(() => { let currentIndex = 0; const totalData = [...largeData]; const loadBatch = () => { const endIndex = Math.min(currentIndex + batchSize, totalData.length); setTableData(prev => [...prev, ...totalData.slice(currentIndex, endIndex)]); currentIndex = endIndex; if (currentIndex < totalData.length) { // 利用requestIdleCallback在浏览器空闲时加载下一批 requestIdleCallback(loadBatch); } }; loadBatch(); return () => { currentIndex = totalData.length; // 清理时终止后续加载 }; }, []); return ( <MaterialReactTable columns={columnsList} data={tableData} /> );
3. 避免不必要的重渲染
- 用
React.memo包裹表格组件,确保只有data或columns变化时才重渲染; - 用
useMemo缓存columns和经过处理的数据,避免每次渲染都重新生成:
const memoizedColumns = useMemo(() => columnsList, []); const processedData = useMemo(() => { // 如果需要对大数据做格式化等处理,这里用useMemo缓存结果 return [...largeData]; }, []); const [tableData, setTableData] = useState([]); useEffect(() => { setTableData(processedData); }, [processedData]); return ( <MaterialReactTable columns={memoizedColumns} data={tableData} /> );
4. 异步处理大数据计算
如果需要对大数据做复杂处理(比如过滤、排序、格式化),把这些逻辑放到Web Worker中,避免阻塞主线程:
// 主线程代码 const [tableData, setTableData] = useState([]); useEffect(() => { const worker = new Worker('./dataProcessor.js'); worker.postMessage(largeData); worker.onmessage = (e) => { setTableData(e.data); worker.terminate(); }; return () => worker.terminate(); }, []); // dataProcessor.js(Web Worker文件) self.onmessage = (e) => { const processedData = e.data.map(item => { // 这里做复杂的数据处理逻辑 return { ...item, formattedDate: new Date(item.date).toLocaleString() }; }); self.postMessage(processedData); };
5. 优化延迟加载方案(替代固定超时)
如果暂时无法实现上述方案,用requestIdleCallback替代setTimeout,让数据加载在浏览器空闲时执行,比固定延迟更合理:
const [tableData, setTableData] = useState([]); useEffect(() => { let idleCallbackId; const loadData = () => { setTableData(stateTable.recentSmsDataRed); }; idleCallbackId = requestIdleCallback(loadData); return () => { cancelIdleCallback(idleCallbackId); }; }, [stateTable.recentSmsDataRed]); return ( <MaterialReactTable columns={columnsList} data={tableData} /> );
内容的提问来源于stack exchange,提问作者Santhosh
相关产品推荐
相关产品推荐

