Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Material-UI Data Grid onSortModelChange Causing an Infinite Loop

I'm following the Sort Model documentation (https://material-ui.com/components/data-grid/sorting/#basic-sorting) and am using sortModel and onSortModelChange exactly as used in the documentation. However, I'm getting an infinite loop immediately after loading the page (I can tell this based on the console.log).

What I've tried:

  • Using useCallback within the onSortChange prop
  • Using server side sorting (https://material-ui.com/components/data-grid/sorting/#server-side-sorting)
  • Using if (sortModel !== model) setSortModel(model) within the onSortChange function.

I always end up with the same issue. I'm using Blitz.js.

My code:

useState:

const [sortModel, setSortModel] = useState<GridSortModel>([
    {
      field: "updatedAt",
      sort: "desc" as GridSortDirection,
    },
  ])

rows definition:

  const rows = 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,
    }
  })

columns definition:


  const columns = [
    { field: "id", headerName: "ID", width: 70, hide: true },
    {
      field: "business_name",
      headerName: "Business Name",
      width: 200,
      // Need renderCell() here because this is a link and not just a string
      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" },
  ]

Rendering DataGrid and using sortModel/onSortChange

      <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={{
            items: [{ columnField: "archived", operatorValue: "is", value: showArchived }],
          }}
          sortModel={sortModel}
          onSortModelChange={(model) => {
            console.log(model)
            //Infinitely logs model immediately
            setSortModel(model)
          }}
        />
      </div>

Thanks in advance!

like image 561
Colton Avatar asked Aug 31 '21 19:08

Colton


2 Answers

I fixed this by wrapping rows and columns in useRefs and used their .current property for both of them. Fixed it immediately.

like image 145
Colton Avatar answered Oct 21 '22 07:10

Colton


Could not understand what the top post meant by using useRef, but the below solution is what worked for me:

    const [sortModel, setSortModel] = useState<GridSortModel>([
        {
            field: 'created',
            sort: 'desc',
        },
    ]);

    const handleSortChange = (model: GridSortModel) => {
        /* if statement to prevent the infinite loop by confirming model is 
         different than the current sortModel state */
        if (JSON.stringify(model) !== JSON.stringify(sortModel)) {
            setSortModel(model);
        }
    };

    <DataGrid
    rows={taskData}
    columns={myWorkColumns}
    sortModel={sortModel}
    onSortModelChange={(model) => handleSortChange(model)}
    />
like image 1
Colegit Avatar answered Oct 21 '22 07:10

Colegit