如何在MUI DataGrid渲染完成后懒加载指定列数据?
实现MUI DataGrid表格渲染后延迟加载指定列数据
当然可以实现,核心是把数据请求从单元格渲染逻辑中剥离,避免在renderCell里直接发起请求(会触发大量重复请求、拖慢表格渲染),改用以下思路:
解决方案步骤
- 先加载表格核心数据(不含耗时的
location列),完成表格渲染 - 监听表格渲染完成/可见行变化事件,批量发起
location数据请求 - 用react-query管理请求状态与缓存,单元格根据缓存状态显示加载器或数据
代码示例(虚拟化表格场景,仅加载可见行数据)
import { DataGrid } from '@mui/x-data-grid'; import { useQuery } from '@tanstack/react-query'; import CircularProgress from '@mui/material/CircularProgress'; import { useEffect, useRef, useState } from 'react'; const MyDataGrid = () => { const gridRef = useRef(null); const [initialRows, setInitialRows] = useState([]); const [visibleRowIds, setVisibleRowIds] = useState([]); // 1. 加载表格核心数据(不含location) const { data: initialData } = useQuery({ queryKey: ['gridInitialData'], queryFn: () => fetch('/api/grid-initial-data').then(res => res.json()), }); useEffect(() => { if (initialData) setInitialRows(initialData); }, [initialData]); // 2. 监听可见行变化,仅加载当前屏幕内的行数据(适合虚拟化表格) const handleRowsVisibleChange = ({ params }) => { const ids = params.rows.map(row => row.id); setVisibleRowIds(ids); }; // 3. 批量请求可见行的location数据 const { data: locationData, isLoading: locationsLoading } = useQuery({ queryKey: ['locationData', visibleRowIds], queryFn: () => fetch(`/api/locations?ids=${visibleRowIds.join(',')}`).then(res => res.json()), enabled: visibleRowIds.length > 0, // 有可见行时才发起请求 }); // 把返回数据转成id为key的映射,方便单元格快速查找 const locationMap = locationData ? Object.fromEntries(locationData.map(item => [item.id, item.location])) : {}; // 列配置 const columns = [ // 其他核心列... { field: "location", headerName: "Location", flex: 1, minWidth: 300, renderCell: (params) => { const location = locationMap[params.row.id]; // 数据未就绪且正在加载时显示加载器 if (!location && locationsLoading) { return <CircularProgress size={20} />; } // 显示数据或默认值 return location || '暂无数据'; }, }, ]; return ( <div style={{ height: 600, width: '100%' }}> <DataGrid ref={gridRef} rows={initialRows} columns={columns} onRowsVisibleChange={handleRowsVisibleChange} initialState={{ pagination: { paginationModel: { page: 0, pageSize: 10 } }, }} pageSizeOptions={[10, 20]} /> </div> ); }; export default MyDataGrid;
非虚拟化场景(一次性加载所有行数据)
如果不需要虚拟化,可在表格核心数据加载完成后直接发起全量请求:
useEffect(() => { if (initialRows.length > 0) { setVisibleRowIds(initialRows.map(row => row.id)); } }, [initialRows]);
关键注意点
- 后端API最好支持批量查询id(如
/api/locations?ids=1,2,3),减少请求次数 - 利用react-query的缓存机制,用户滚动回已加载的行时直接复用缓存,无需重复请求
- 若后端不支持批量查询,可改用
useQueries发起单个请求,但需注意控制并发量
内容的提问来源于stack exchange,提问作者Abasaheb Gaware
相关产品推荐
相关产品推荐

