agGrid in react + redux app is modifying underlying data

前端 未结 1 402
长发绾君心
长发绾君心 2020-12-20 03:13

I\'m using latest agGrid enterprise in react + redux app.

The issue is that I\'m using built in editing of agGrid and this is modifying directly underlying data i.e

相关标签:
1条回答
  • 2020-12-20 03:57

    EDIT: Expanding my answer with more detail.

    You have to set a "valueSetter" function, and set it on each column. Easiest way to do that is with the defaultColDef. Quick note, each row in my table is a 'transaction', so you'll see reference to transactions, versus some other form of identification.

    For example:

    <AgGridReact
          // OPTIONS REQUIRED FOR OPTIMIZATION WITH REACT
          reactNext
          deltaRowDataMode
          getRowNodeId={data => data.transaction_id}
    
          // OTHER OPTIONS
          rowSelection="multiple"
          editType="fullRow"
    
          // TABLE DATA
          defaultColDef={{ ...defaultColDef, valueSetter }}
          columnDefs={columns}
          rowData={transactions}
    
          // DISPLAY
          rowClassRules={rowClassRules}
    
           // EVENTS
          onGridReady={onGridReady}
          onRowEditingStarted={onRowEditingStarted}
          onRowEditingStopped={onRowEditingStopped}
    
        />
    

    Don't forget the optimization items required for react and redux. (reactNext, deltaRowDataMode, getRowNodeId).

    The defaultColDef I have defined is simple:

    defaultColDef: {
      resizable: true,
      sortable: true,
      filter: true,
      editable: true,
    },
    

    And the valueSetter is a function defined very simply as:

    const valueSetter = (params) => {
      allActions.columnEdit(params.data, params.oldValue, params.newValue, params.colDef);
      return false;
    };
    

    Where the allActions.columnEdit is just calling my Redux action I have defined in an import and then bound with connect() and mapDispatchToProps. The return false is what's required to prevent the mutating of the state. Make sure that your redux action handles whatever you need to do. Here's my example:

      case actionTypes.COLUMN_EDIT: {
      // FOR EACH COLUMN EDITED, CHECK IF ANYTHING CHANGED
      // POST CHANGES TO NEW STATE
      if (payload.oldValue !== payload.newValue) {
        const account = 'acct01';
        const column = payload.colDef.field;
        const index = state[account].transactions.findIndex(
          t => t.transaction_id === payload.t.transaction_id,
        );
        return produce(state, (draft) => {
          const transaction = draft[account].transactions[index];
          transaction[column] = payload.newValue;
        });
      }
      return state;
    }
    

    Hope this helps. Seems to be a LOT of extra workaround for what should be handled directly by Ag-Grid, but maybe they'll put some future development into it.

    https://www.ag-grid.com/javascript-grid-value-setters/

    0 讨论(0)
提交回复
热议问题