Material-UI Data Grid onSortModelChange触发无限循环问题求解
问题根因
你的无限循环是两个问题共同触发的:
sortModel是数组引用类型,你之前写的if (sortModel !== model)是引用全等判断,onSortModelChange每次返回的model都是新的数组实例,和state中sortModel的引用永远不相等,判断会永久成立,每次都触发setSortModel导致组件重渲染。- 你的
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
相关产品推荐
相关产品推荐

