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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:15:28