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
相关产品推荐
相关产品推荐

