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

React中MUI DataGrid使用renderCell触发无限更新深度超限报错求助

问题根源
  • 核心是每次组件渲染时都会通过formatColumns生成全新的列配置对象,传递给MUI DataGrid的columns属性每次都是新的引用,MUI检测到columns变化会触发全量重渲染。你点击行触发setRightSlidePlaneOpen更新父组件状态后,当前表格组件会重渲染,再次生成新的columns,触发DataGrid再次重渲染,和状态更新形成循环,导致超出最大更新深度。
  • 额外问题:你将JSX元素直接存在rightSlidePlaneContent状态中,JSX绑定的闭包函数会随着组件重渲染变化,也会引发不必要的重渲染和状态异常。
解决方法
  1. 用useMemo缓存格式化后的列配置,只有原始columns变化时才重新生成:
import { useMemo } from 'react';

// 组件内
const formattedColumns = useMemo(() => {
  return formatColumns(columns);
}, [columns]);

// DataGrid绑定缓存后的columns
<DataGrid
  columns={formattedColumns}
  // 其他属性保持不变
/>
  1. 不要在状态中存储JSX元素,改为存储侧边栏配置,渲染时动态生成内容:
    父组件修改状态定义:
// 替换原来的rightSlidePlaneContent状态
const [rightSlideConfig, setRightSlideConfig] = useState<{
  type: 'view' | 'add' | null;
  params?: any;
  isLarge?: boolean;
}>({ type: null });

修改打开侧边栏的逻辑:

const openViewPane = (params: GridRowParams, e): void => {
  setRightSlideConfig({
    type: 'view',
    params,
    isLarge: true
  });
  setRightSlidePlaneOpen(true);
};

const openAddForm = (): void => {
  setRightSlideConfig({
    type: 'add'
  });
  setRightSlidePlaneOpen(true);
};

侧边栏渲染时动态生成内容:

// PersistentDrawerRight组件内或者父组件传入content时生成
const getSlideContent = () => {
  switch(rightSlideConfig.type) {
    case 'view':
      return <ViewAccountPane close={closeForm} params={rightSlideConfig.params} />;
    case 'add':
      return <AddForm category={'tag'} close={closeAddForm} title={ADD_FORM_TITLE} createFunction={createTag} />;
    default:
      return <></>;
  }
};

<PersistentDrawerRight
  content={getSlideContent()}
  open={rightSlidePlaneOpen}
  rspLarge={rightSlideConfig.isLarge || false}
/>
  1. 如果单元格内添加了按钮,需要在按钮点击事件中添加e.stopPropagation()阻止事件冒泡到行,避免触发行点击逻辑。
不使用renderCell添加列按钮的方法

MUI DataGrid提供了专门的操作列类型,不需要手动实现renderCell,官方推荐写法如下:

import { GridActionsCellItem, GridColDef } from '@mui/x-data-grid';
import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/Delete';

const columns: GridColDef[] = [
  // 其他列配置
  {
    field: 'actions',
    type: 'actions', // 指定为操作列类型
    headerName: '操作',
    width: 120,
    getActions: (params) => [
      <GridActionsCellItem
        icon={<EditIcon />}
        label="编辑"
        onClick={(e) => {
          e.stopPropagation();
          // 编辑逻辑
        }}
      />,
      <GridActionsCellItem
        icon={<DeleteIcon />}
        label="删除"
        onClick={(e) => {
          e.stopPropagation();
          // 删除逻辑
        }}
      />
    ]
  }
];

这种写法内置了单元格样式适配,不需要手动处理renderCell的布局问题。

内容的提问来源于stack exchange,提问作者erick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 10:57:01