Material UI DataGrid Pro异步渲染头像列报错,求非整行重渲染方案
解决Material UI DataGrid Pro异步加载头像列的问题(避免整行重渲染)
问题根源很明确:renderCell 要求同步返回JSX元素,而你用了async函数,它返回的是Promise,这就导致了报错。要实现异步加载头像+骨架图,同时不触发整行重渲染,最佳方案是把异步逻辑封装到独立组件中。
步骤1:创建异步头像组件
这个组件内部管理加载状态和图片URL,只会更新自身,不会影响DataGrid的整行渲染:
import { Avatar, Skeleton } from '@mui/material'; import { useEffect, useState } from 'react'; import { getDownloadURL, ref, storage } from 'firebase/storage'; interface AsyncAvatarProps { storagePath: string; altText: string; } const AsyncAvatar = ({ storagePath, altText }: AsyncAvatarProps) => { const [imageUrl, setImageUrl] = useState<string | null>(null); const [isLoading, setIsLoading] = useState(true); // 缓存已加载的图片URL,避免重复请求 const imageCache = new Map<string, string>(); useEffect(() => { const fetchImage = async () => { // 先查缓存 if (imageCache.has(storagePath)) { setImageUrl(imageCache.get(storagePath)!); setIsLoading(false); return; } try { const url = await getDownloadURL(ref(storage, storagePath)); setImageUrl(url); imageCache.set(storagePath, url); } catch (err) { console.error('头像加载失败:', err); // 可选:设置默认头像地址 // setImageUrl('/default-avatar.png'); } finally { setIsLoading(false); } }; fetchImage(); }, [storagePath]); // 加载中显示骨架图 if (isLoading) { return <Skeleton variant="circular" width={50} height={50} sx={{ mt: 1, mb: 1 }} />; } return ( <Avatar alt={altText} src={imageUrl || undefined} sx={{ width: 50, height: 50, mt: 1, mb: 1 }} /> ); }; export default AsyncAvatar;
步骤2:在DataGrid列配置中使用该组件
修改你的renderCell,同步返回AsyncAvatar组件即可:
{ field: "avatar", headerName: "", headerClassName: "tableHeader", width: 80, cellClassName: "profilePictureCell", renderCell: (params: GridRenderCellParams<CounselorDashboardStudentRow>) => { return ( <AsyncAvatar storagePath={params.value} altText={`${params.row.firstName} ${params.row.lastName}`} /> ); }, },
为什么这个方案有效?
renderCell现在同步返回JSX组件,符合DataGrid的要求,不会返回Promise。- 异步逻辑被封装在
AsyncAvatar内部,组件自身的状态更新只会触发自身重渲染,不会导致整行刷新。 - 加入了缓存机制,同一个头像地址只会请求一次,提升性能。
- 加载过程中显示骨架图,优化用户体验。
内容的提问来源于stack exchange,提问作者RyanY
相关产品推荐
相关产品推荐

