'How do I change state of MUI Data Grid when using a checkbox in cellRender?

So I have a fairly simple scenario I'm working with where I need a checkbox in a MUI data grid, but not using checkboxSelection. It's easy enough for me to render my checkbox in a column, but I can't really figure out how to change the state of that grid row once I check the box. The function receives the event object and you can access the target element, but I'm trying to actually change the value of the confirmed property on the row.

Here's the sample code for the component.

import React, { useState, useEffect } from 'react'
import { Checkbox } from '@mui/material';
import { DataGrid } from '@mui/x-data-grid'

const DataTable = () => {

    const [tableData, setTableData] = useState([])

    function handleConfirmChange() {
      console.log('How do I change row state here????');
    }

    const columns = [
      { field: 'title', headerName: 'Title', width: 200 },
      { field: 'body', headerName: 'Body', width: 600 },
      {
        field: 'confirmed',
        headerName: 'Confirmed',
        renderCell: (params) => (
          <Checkbox
            checked={params.confirmed===1}
            onChange={handleConfirmChange}
          />
        ),
      }
    ]

    useEffect(() => {
        fetch("https://jsonplaceholder.typicode.com/posts")
          .then((data) => data.json())
          .then((data) => {
            for (var i=0; i<data.length; i++) {
              data[i].confirmed = false;
            }
            setTableData(data);
          })
    
      }, [])

  return (
    <div style={{ height: 700, width: '100%' }}>
      <DataGrid
        rows={tableData}
        columns={columns}
        pageSize={12}
      />
    </div>
  )
}

export default DataTable


Solution 1:[1]

In the checked={params.confirmed===1} statement, the confirmed in the params property is not the property from the tableData. It is the columns' field name.

To get the clicked row, we have to set Id for each row, pass the rowId as param from the checkbox, then we can identify the clicked row.

So, in the useEffect hook, we have to set the rowId based on the index.

useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((data) => data.json())
      .then((data) => {
        setTableData(
          data.map((x, index) => ({
            ...x,
            rowId: index,
            confirmed: false
          }))
        );
      });
  }, []);

Then pass the row as param in the checkbox click event. Also, set the checked property as params.rows?.confirmed. The params.rows gives the actual row data. The rows maybe null during the initialization, so we have to set Optional chaining (?.) to the confirmed property.

 <Checkbox
   checked={params.rows?.confirmed}
   onChange={() => handleConfirmChange(params.row)}
 />

In the handleConfirmChange function, get the clicked row and update the confirmed property. Loop through the tableData array and get the clicked row, then set the confirmed and update the grid.

function handleConfirmChange(clickedRow) {
const updatedData = tableData.map((x) => {
  if (x.rowId === clickedRow.rowId) {
    return {
      ...x,
      confirmed: !clickedRow.confirmed
    };
  }
  return x;
});
setTableData(updatedData);

}

Here is the updated working code and codesandbox.

import React, { useState, useEffect } from "react";
import { Checkbox } from "@mui/material";
import { DataGrid } from "@mui/x-data-grid";

export default function DataTable() {
  const [tableData, setTableData] = useState([]);

  function handleConfirmChange(clickedRow) {
    const updatedData = tableData.map((x) => {
      if (x.rowId === clickedRow) {
        return {
          ...x,
          confirmed: true
        };
      }
      return x;
    });
    setTableData(updatedData);
  }

  const columns = [
    { field: "title", headerName: "Title", width: 200 },
    { field: "body", headerName: "Body", width: 400 },
    {
      field: "confirmed",
      headerName: "Confirmed",
      renderCell: (params) => (
        <Checkbox
          checked={params.rows?.confirmed}
          onChange={() => handleConfirmChange(params.row.rowId)}
        />
      )
    }
  ];

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((data) => data.json())
      .then((data) => {
        setTableData(
          data.map((x, index) => ({
            ...x,
            rowId: index,
            confirmed: false
          }))
        );
      });
  }, []);

  return (
    <div style={{ height: 400, width: "100%" }}>
      <DataGrid
        rows={tableData}
        columns={columns}
        pageSize={12}
        rowsPerPageOptions={[12]}
      />
    </div>
  );
}

Edit SOQ-71445011-MUI-DataGrid

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1