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

MUI DataGrid中Select组件性能优化:避免单元格重复useState

MUI DataGrid 自定义Select列性能优化方案

问题背景

使用MUI DataGrid组件构建表格时,为某一列的所有单元格添加了Select组件,通过自定义Payment组件传入renderCell实现编辑功能。但每个单元格的Payment组件都维护独立的useState实例,导致表格性能下降,需要优化。

原代码如下:

const Payment = (params) => {
    const [paymentStatus, setPaymentStatus] = useState(params.value);
    const id = params.id;

    return (
      <Select
        value={paymentStatus}
        onChange={(e) => {
          setPaymentStatus(e.target.value);
          return updateSubscription(id, e.target.value); // 更新支付状态的函数
        }}
      >
        <MenuItem value="paid">Paid</MenuItem>
        <MenuItem value="unpaid">Un Paid</MenuItem>
      </Select>
    );
};
const columns = [
  // 其他列配置
  {
    field: "payment_status",
    headerName: "Payment Status",
    renderCell: (params) => <Payment params={params} />,
  }
];

优化方案

1. 状态提升至父组件统一管理

将所有行的支付状态集中存放在父组件的状态中,避免每个单元格维护独立状态,减少组件重渲染次数。

父组件代码示例:

// 父组件中维护所有行的支付状态
const [paymentStates, setPaymentStates] = useState({});

// 初始化时从表格数据同步状态
useEffect(() => {
  const initialStates = {};
  rows.forEach(row => {
    initialStates[row.id] = row.payment_status;
  });
  setPaymentStates(initialStates);
}, [rows]);

// 更新状态的函数
const handlePaymentChange = (id, newValue) => {
  setPaymentStates(prev => ({ ...prev, [id]: newValue }));
  updateSubscription(id, newValue);
};

修改后的Payment组件:

const Payment = ({ params, paymentStates, onPaymentChange }) => {
  const { id, value } = params;
  const currentStatus = paymentStates[id] ?? value;

  return (
    <Select
      value={currentStatus}
      onChange={(e) => onPaymentChange(id, e.target.value)}
    >
      <MenuItem value="paid">Paid</MenuItem>
      <MenuItem value="unpaid">Un Paid</MenuItem>
    </Select>
  );
};

列配置修改:

const columns = [
  // 其他列配置
  {
    field: "payment_status",
    headerName: "Payment Status",
    renderCell: (params) => (
      <Payment 
        params={params} 
        paymentStates={paymentStates} 
        onPaymentChange={handlePaymentChange} 
      />
    ),
  }
];

2. 利用DataGrid内置可编辑模式

DataGrid原生支持可编辑列,无需自定义renderCell,直接配置editable和editComponent,由DataGrid统一管理编辑状态,性能更优。

列配置修改示例:

const columns = [
  // 其他列配置
  {
    field: "payment_status",
    headerName: "Payment Status",
    editable: true,
    editComponent: (params) => (
      <Select
        value={params.value}
        onChange={(e) => params.onChange(e.target.value)}
        onBlur={params.onBlur}
      >
        <MenuItem value="paid">Paid</MenuItem>
        <MenuItem value="unpaid">Un Paid</MenuItem>
      </Select>
    ),
    // 可选:配置编辑完成后的回调,同步到后端
    onCellEditCommit: (params) => {
      updateSubscription(params.id, params.value);
    }
  }
];

3. 使用React.memo优化组件重渲染

如果必须保留组件内的状态,用React.memo包裹Payment组件,避免无意义的重渲染(仅当params变化时才重新渲染)。

修改后的Payment组件:

const Payment = React.memo((params) => {
    const [paymentStatus, setPaymentStatus] = useState(params.value);
    const id = params.id;

    return (
      <Select
        value={paymentStatus}
        onChange={(e) => {
          setPaymentStatus(e.target.value);
          updateSubscription(id, e.target.value);
        }}
      >
        <MenuItem value="paid">Paid</MenuItem>
        <MenuItem value="unpaid">Un Paid</MenuItem>
      </Select>
    );
}, (prevProps, nextProps) => {
  // 自定义比较逻辑,仅当value或id变化时才重渲染
  return prevProps.params.value === nextProps.params.value && 
         prevProps.params.id === nextProps.params.id;
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:05:30