How to dynamically update MaterialUI DataGrid table in React JS

13,503

The issue here is that you are not keeping the state of your data. I see you've attempted to use hooks - these will not work inside a class component so just use the state class property

class ElgibleContracts extends Component {
  //const [rows, setRows] = useState(data); <-- this will not work in class component
  //const [deletedRows, setDeletedRows] = useState([]); <-- this will not work in class component

  state = {
    data: data // use state class property instead
  };

Inside your handlePurge method, this is where you set the new state for the filtered data

let data_to_be_kept = this.state.data.filter(function (item) {
  return rowsToBeDeleted.includes(item.id) === false;
});

this.setState({
  data: data_to_be_kept
});

Finally, in your DataGrid, the value of prop rows should be assigned the value of the state data

<DataGrid
  rows={this.state.data}
  columns={columns}
  pageSize={10}
  checkboxSelection
  onRowSelected={this.handleRowSelection}
/>

Edit hopeful-bouman-6s9mo

Share:
13,503
coder_coder123
Author by

coder_coder123

Updated on July 25, 2022

Comments

  • coder_coder123
    coder_coder123 almost 2 years

    here's the general synopsis of what I'm trying to do:

    • When the user clicks a checkbox in a row, that row is saved from being deleted (typically the user will click more than row).
    • Every record without a checked checkbox is deleted once the user hits "purge records" button.

    I got some general advice on how to do it, and I used the advice I was given accompanied by my own logic to come up with an implementation. The issue is that although I think my logic looks good and all my console.log statements looks good, the data in the isn't updating. BTW, this is in a JSX file & not just a plain JS file.

    I've been stuck on this for like a day now, and I'm genuinely stuck as to what my problem is/why this isn't working. Thank you for all your help and suggestions


    import React, { Component, useState } from "react";
    import { DataGrid } from "@material-ui/data-grid";
    import Button from "@material-ui/core/Button";
    import DeleteIcon from '@material-ui/icons/Delete';
    const columns = [
      { field: "id", headerName: "ID", width: 70 },
      { field: "firstName", headerName: "First name", width: 130 },
      { field: "lastName", headerName: "Last name", width: 130 },
      { field: "age", headerName: "Age", type: "number", width: 90 },
      { field: "fullName", headerName: "Full name", description: "This column has a value getter and is not sortable.", 
        sortable: false,
        width: 160,
        valueGetter: (params) =>
          `${params.getValue("firstName") || ""} ${
            params.getValue("lastName") || ""
          }`
      },
      { field: "city", headerName: "City", width: 100 },
      { field: "state", headerName: "State", width: 100 }
    ];
    
    var data = [
      {
        id: 1,
        lastName: "Snow",
        firstName: "Jon",
        age: 35,
        city: "Milwaukee",
        state: "Wisconsin"
      },
      {
        id: 2,
        lastName: "Lannister",
        firstName: "Cersei",
        age: 42,
        city: "Dubuque",
        state: "Iowa"
      },
      {
        id: 3,
        lastName: "Lannister",
        firstName: "Jaime",
        age: 45,
        city: "Appleton",
        state: "Wisconsin"
      },
      {
        id: 4,
        lastName: "Stark",
        firstName: "Arya",
        age: 16,
        city: "Madison",
        state: "Wisconsin"
      },
      {
        id: 5,
        lastName: "Targaryenmnsdlfbsjbgjksbgksbfksfgbk",
        firstName: "Daenerys",
        age: null,
        city: "Green Bay",
        state: "Wisconsin"
      },
      {
        id: 6,
        lastName: "Melisandre",
        firstName: null,
        age: 150,
        city: "San Antonio",
        state: "Texas"
      },
      {
        id: 7,
        lastName: "Clifford",
        firstName: "Ferrara",
        age: 44,
        city: "Dallas",
        state: "Texas"
      },
      {
        id: 8,
        lastName: "Frances",
        firstName: "Rossini",
        age: 36,
        city: "Brooklyn",
        state: "New York"
      },
      {
        id: 9,
        lastName: "Roxie",
        firstName: "Harvey",
        age: 65,
        city: "Toledo",
        state: "Ohio"
      },
      {
        id: 10,
        lastName: "Larry",
        firstName: "King",
        age: 105,
        city: "Chicago",
        state: "Illiniois"
      },
      {
        id: 11,
        lastName: "Snow",
        firstName: "Jon",
        age: 35,
        city: "Milwaukee",
        state: "Wisconsin"
      },
      {
        id: 12,
        lastName: "Lannister",
        firstName: "Cersei",
        age: 42,
        city: "Dubuque",
        state: "Iowa"
      },
      {
        id: 13,
        lastName: "Lannister",
        firstName: "Jaime",
        age: 45,
        city: "Appleton",
        state: "Wisconsin"
      },
      {
        id: 14,
        lastName: "Stark",
        firstName: "Arya",
        age: 16,
        city: "Madison",
        state: "Wisconsin"
      },
      {
        id: 15,
        lastName: "Targaryenmnsdlfbsjbgjksbgksbfksfgbk",
        firstName: "Daenerys",
        age: null,
        city: "Green Bay",
        state: "Wisconsin"
      },
      {
        id: 16,
        lastName: "Melisandre",
        firstName: null,
        age: 150,
        city: "San Antonio",
        state: "Texas"
      },
      {
        id: 17,
        lastName: "Clifford",
        firstName: "Ferrara",
        age: 44,
        city: "Dallas",
        state: "Texas"
      },
      {
        id: 18,
        lastName: "Frances",
        firstName: "Rossini",
        age: 36,
        city: "Brooklyn",
        state: "New York"
      },
      {
        id: 19,
        lastName: "Roxie",
        firstName: "Harvey",
        age: 65,
        city: "Toledo",
        state: "Ohio"
      },
      {
        id: 20,
        lastName: "Larry",
        firstName: "King",
        age: 105,
        city: "Chicago",
        state: "Illiniois"
      }
    ];
    
    var rowsToKeep = [];
    var rowsToBeDeleted = [];
    
    class ElgibleContracts extends Component {
      //const [rows, setRows] = useState(data);
      //const [deletedRows, setDeletedRows] = useState([]);
    
      /*
      * It's assumed that the user will want to delete all the rows,
      * but there will be scenarios when that's not the case.
      */
      setRowsToBeDeleted = () => {
        for (var i = 0; i < data.length; i++){
          rowsToBeDeleted.push(data[i].id);
        }
        rowsToBeDeleted = [...new Set(rowsToBeDeleted)]; //Did this because clicking the button twice will make doubles appear for each row
        
      };
    
      /*
       * This method fires off when the checkbox is clicked for a given row.
      */
      handleRowSelection = (e) => {
        // remove it if it's already present - this means the user unchecked it
        if (rowsToKeep.includes(e.data.id)){
          for(var i = 0; i < rowsToKeep.length; i++){ 
            if (rowsToKeep[i] === e.data.id){ 
              rowsToKeep.splice(i, 1); 
            }
          }
        } else {
          // user clicked it - add it to the list of rows to keep.
          rowsToKeep.push(e.data.id);
        }
    
        this.setRowsToBeDeleted();
        console.log("Rows to Keep: " + rowsToKeep);
        //setDeletedRows([...deletedRows, ...rows.filter((r) => r.id === e.data.id)]);
        //console.log("All rows: " + rows);
      };
    
      /*
      * This method updates the data that's to be displayed.
      */
      handlePurge = () => {
        // Check to see what rows are to be deleted and which ones aren't.
        for (var j = 0; j < rowsToKeep.length; j++){
          if (rowsToBeDeleted.includes(rowsToKeep[j])){
            // delete it from 'rows to be deleted' array
            console.log("Found:" + rowsToKeep[j]);
            while(rowsToBeDeleted.indexOf(rowsToKeep[j]) !== -1) {
              rowsToBeDeleted.splice(rowsToBeDeleted.indexOf(rowsToKeep[j]), 1)
            }
          } else {
            // do nothing
          }
        } 
    
        // remove it from the data set. Just used ID of 1 in this case to test whether or not it would work
        data = data.filter(function(item) { 
          return item.id !== 1;  
        });
        
        console.log("Rows to Delete: " + rowsToBeDeleted);
        console.log("Here are deleted items",rowsToBeDeleted);
      };
    
      render(){
        return (
        <div style={{ textAlign: "center" }}>
          <h1 style={{ fontFamily: "Stone" }}>Elgible Contracts</h1>
          <span className="horizontal-line" />
          <div className="centerDiv" style={{ height: 380, width: 950 }}>
            <DataGrid
              rows={data}
              columns={columns}
              pageSize={10}
              checkboxSelection
              onRowSelected={this.handleRowSelection}
            />
          </div>
          <br />
          <Button variant="contained" color="primary" startIcon={<DeleteIcon />} style={{textTransform: "none"}} onClick={this.handlePurge}>
            Purge Records
          </Button>
        </div>
      );
    };
    }
    
    export default ElgibleContracts;
    

    enter image description here

  • Oron Bendavid
    Oron Bendavid over 3 years
    I'm getting same error with hooks. Do you have any idea if it support it?
  • 95faf8e76605e973
    95faf8e76605e973 over 3 years
    regardless of class or function (i.e., hooks) it should work. to answer your question, yes - MUI DataGrid supports hooks. the general idea of how to solve this is to simply have the prop rows to have a dynamic value which is bound to a state. when the state updates, the DataGrid updates
  • Oron Bendavid
    Oron Bendavid over 3 years
    Thanks. I created simple example with useState for rows, but I'm facing super slow performance and data rendring. Currently I try to understand if it is related to a mismatch versions with react or react-dom
  • 95faf8e76605e973
    95faf8e76605e973 over 3 years
    if you are dealing with big data, i suggest you look into virtualized tables. here is an example from mui docs: material-ui.com/components/tables/#virtualized-table
  • Oron Bendavid
    Oron Bendavid over 3 years
    Thanks for the info, my example uses small data, I fixed the issue by updating packages to "@material-ui/data-grid": "4.0.0-alpha.10", "@material-ui/core": "4.11.1", "react": "^17.0.1".
  • hfontanez
    hfontanez over 2 years
    Is the logic backwards? Shouldn't "purge" function delete the selected rows? It is actually keeping the selected.