Search code examples
ag-gridmobxmobx-reactmobx-react-lite

Mobx Store does not update rows in AGGrid


I want to use mobx store for state management. I want to update record in the store and it should be reflected in the grid. I have method updateRecord which is updating the store but the AGgrid does not get updated. Another method deleteRecord works perfectly fine and it updates store as well as grid.

I have tried two ways to update the store but none of this works.

this.gridData[index] = { id: 1, name: 'XX John' } //update the complete object
this.gridData[index].name = 'XX John'; // update specific property of object

How to make updateRecord method work ? Please provide any pointers.

Complete Source Code.

import React, { useState } from 'react';

import { observable, action, makeAutoObservable } from 'mobx';
import { AgGridReact } from 'ag-grid-react';

import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { observer } from 'mobx-react-lite';

interface IEmployee {
  id: number;
  name: string;
}

class MyStore {
  gridData: IEmployee[] = [
    { id: 1, name: 'John' },
    { id: 2, name: 'Jane' }
  ];

  constructor() {
    makeAutoObservable(this, {
      gridData: observable,
      updateRecord: action,
      deleteRecord: action
    });
  }

  updateRecord(id: number, newData: { name: string }) {
    const index = this.gridData.findIndex((record) => record.id === id);
    //this.gridData[index] = { id: 1, name: 'XX John' }
    //this.gridData[index].name = 'XX John';
  }

  deleteRecord(id: number) {
    this.gridData = this.gridData.filter((record) => record.id !== id);
  }
}

const store = new MyStore();

const MyComponent = observer(() => {
  const [colDefs, setColDefs] = useState([{ field: 'id' }, { field: 'name' }]);

  const { gridData } = store;

  return (
    <div>
      <div className="ag-theme-alpine" style={{ height: 400, width: 600 }}>
        <AgGridReact rowData={gridData} columnDefs={colDefs}></AgGridReact>
      </div>
      <button onClick={() => store.updateRecord(1, { name: 'Updated John' })}>
        Update record
      </button>
      <button onClick={() => store.deleteRecord(2)}>Delete record</button>
    </div>
  );
})

Solution

  • AgGridReact probably only updates when rowData (gridData) changes entirely (changes reference), it probably can't know that just some property of some inner object was updated.

    I think the easiest way would be to just use toJS (https://mobx.js.org/api.html#tojs) MobX method to transform your observable value to regular JS object.

    <AgGridReact rowData={toJS(gridData)} columnDefs={colDefs}></AgGridReact>
    

    Your deleteRecord method works because you create new gridData array by using .filter()