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

Material-UI Data Grid onSortModelChange触发无限循环问题求解

问题根因

你的无限循环是两个问题共同触发的:

  1. sortModel是数组引用类型,你之前写的if (sortModel !== model)是引用全等判断,onSortModelChange每次返回的model都是新的数组实例,和state中sortModel的引用永远不相等,判断会永久成立,每次都触发setSortModel导致组件重渲染。
  2. 你的rows、columns、filterModel都没有做引用缓存,每次组件重渲染都会生成新的引用值,DataGrid检测到props变更就会重新执行排序逻辑,再次触发onSortModelChange,形成无限循环。

解决方案

第一步:修改sortModel的比较逻辑,改为深度值比较

如果项目中引入了lodash,直接用_.isEqual做深度比较更稳妥,没有的话可以用JSON.stringify做简单序列化比较:

onSortModelChange={(model) => {
  console.log(model)
  // 深度比较值而非引用
  if (JSON.stringify(sortModel) !== JSON.stringify(model)) {
    setSortModel(model)
  }
}}

第二步:缓存所有传入DataGrid的引用类型props

用useMemo缓存rows、columns、filterModel,避免每次渲染生成新引用:

// 缓存列定义,依赖项填入你用到的外部变量
const columns = useMemo(() => [
  { field: "id", headerName: "ID", width: 70, hide: true },
  {
    field: "business_name",
    headerName: "Business Name",
    width: 200,
    renderCell: (params: GridCellParams) => {
      console.log(params)
      return <BusinessNameLink application={params.row} />
    },
  },
  // 剩余列定义保持不变
  { field: "business_phone", headerName: "Business Phone", width: 180 },
  { field: "applicant_name", headerName: "Applicant Name", width: 180 },
  { field: "applicant_email", headerName: "Applicant Email", width: 180 },
  { field: "owner_cell_phone", headerName: "Ownership/Guarantor Phone", width: 260 },
  { field: "status", headerName: "Status", width: 130 },
  { field: "agent_name", headerName: "Agent", width: 130 },
  { field: "equipment_description", headerName: "Equipment", width: 200 },
  { field: "createdAt", headerName: "Submitted At", width: 250 },
  { field: "updatedAt", headerName: "Last Edited", width: 250 },
  { field: "archived", headerName: "Archived", width: 180, type: "boolean" },
], [])

// 缓存行数据,依赖传入的数据源和日期格式化方法
const rows = useMemo(() => currentUsersApplications.map((application) => {
  return {
    id: application.id,
    business_name: application.business_name,
    business_phone: application.business_phone,
    applicant_name: application.applicant_name,
    applicant_email: application.applicant_email,
    owner_cell_phone: application.owner_cell_phone,
    status: application.status,
    agent_name: application.agent_name,
    equipment_description: application.equipment_description,
    createdAt: formattedDate(application.createdAt),
    updatedAt: formattedDate(application.updatedAt),
    archived: application.archived,
  }
}), [currentUsersApplications, formattedDate])

// 缓存过滤规则,依赖显示归档的状态变量
const filterModel = useMemo(() => ({
  items: [{ columnField: "archived", operatorValue: "is", value: showArchived }],
}), [showArchived])

第三步:修改DataGrid的props引用

把缓存后的变量传入DataGrid,同时可以用useCallback包裹排序回调进一步优化:

const handleSortModelChange = useCallback((model: GridSortModel) => {
  console.log(model)
  if (JSON.stringify(sortModel) !== JSON.stringify(model)) {
    setSortModel(model)
  }
}, [sortModel])

// 组件渲染部分
<div style={{ height: 580, width: "100%" }} className={classes.gridRowColor}>
  <DataGrid
    getRowClassName={(params) => `MuiDataGrid-row--${params.getValue(params.id, "status")}`}
    rows={rows}
    columns={columns}
    pageSize={10}
    components={{
      Toolbar: GridToolbar,
    }}
    filterModel={filterModel}
    sortModel={sortModel}
    onSortModelChange={handleSortModelChange}
  />
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:27:02