I have a data grid as follows from MUI:

<DataGrid
  apiRef={apiRef}
  experimentalFeatures={{ newEditingApi: true }}
  headerHeight={23}
  showCellRightBorder
  showColumnRightBorder
  disableColumnMenu
  onColumnHeaderClick={(params: GridColumnHeaderParams) => {
    setSelectedColumn(params.colDef.field);
  }}
  columns={formattedColumnsToShow}
  rows={timeSheetFees || []}
  rowHeight={29}
  onCellClick={(_params, event) => {
    event.defaultMuiPrevented = true;
  }}
  processRowUpdate={handleProcessRowUpdate}
  onProcessRowUpdateError={handleProcessRowUpdateError}
  throttleRowsMs={1000}
/>

Where the function passed into processRowUpdate is just updating the local state (no backend API calls):

const handleProcessRowUpdate = useCallback(
(newRow: MappedTableEntryRowType) => {
  return processRowUpdate(newRow);
},
[processRowUpdate]);

I have this useEffect where I am trying to update a row (3 different cells within a row):

useEffect(() => {
const updateCurrentCell = async (id: string, field: string, value: string | undefined) => {
  await apiRef.current.setEditCellValue({ id, field, value });
  apiRef.current.stopCellEditMode({ id, field });
};

if (!isEmpty(selectedMatterFromModal)) {
  const id = selectedRow;
  const { matterId } = selectedMatterFromModal;
  const { field } = selectedCell;

  updateCurrentCell(id, field, matterId);

  apiRef.current.updateRows([{ id, matterNo: matterId, matterId, matterDescription: matterId, client: matterId }]);
  setSelectedMatterFromModal({});
}

}, [apiRef, selectedCell, selectedMatterFromModal, selectedRow, setSelectedMatterFromModal]);

But every time processRowUpdate is called, the old row data is passed in, overriding any new values that I have just updated. I have to use a useEffect as the data coming with the new row values is outside of the DataGrid context, so I cannot use an inbuilt callback or anything to achieve this.

How do I fix this?

1

There are 1 best solutions below

0
Mathieu Gros On

I have the same problem, it seems that newRow and oldRow values are inverted in the datagrid processRowUpdate. probably a bug.

I implemented the following workaround while waiting to know the exact solution

This is my issue and my workaround :

//In my custom field : i create the newRow  values when user click on submit
const updateRows = (selectedOptions) => {

let oldRow=props.params.row;
let newRow={...oldRow};
newRow[props.params.colDef.field]=selectedOptions;

//My workaround here : in a "homemade cache" I store a variable indicating that the updateRows api is currently in use
Common.setCache("api.updateRows.used",true);

props.params.api.updateRows([newRow]); 

}

When the above api.updaterows api is executed, this executes the datagrid processRowUpdate also. And here I see the same problem as you, the newRow is not the right one! the oldRow is passed instead. But the old Row variable contains the correct newRow data. So the values ​​seem reversed

So I implemented the following workaround in my Datagrid component:

 const processRowUpdate = (newRow, oldRow,isNew) => {

//I use a homemade cache to store information if I use the API or not. If yes, I re-invert the data to have them in the right variables
if(Common.getCache("api.updateRows.used").data) {
  let prevNewRow={...newRow};
  newRow={...oldRow};
  oldRow={...prevNewRow};
  Common.setCache("api.updateRows.used",false);
}

It works, but it's not clean. I would like to know if it is possible to use only the API