Material UI DataGrid - how to tell which rows user has selected?

Viewed 1864

I am working on creating a website using React and Material UI. I want to know which rows have been selected in my DataGrid.

I want to fill an array with the current selected rows using useState. I am attempting to do so in handleRowSelection.

Currently e.selection model is printing out the correct selected rows, but when I try and put the selected rows in my useState array it skips the first selected row.

For example: If I had selected row 2 and row 4 the e.selection model would print ["2","4"] to the console but select would just print ["4"].

What am I missing? How come select doesn't have the first row selected?

import * as React from 'react';
import { DataGrid } from '@material-ui/data-grid';

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') || ''}`,
  },
];

const rows = [
  { id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 },
  { id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 42 },
  { id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 45 },
  { id: 4, lastName: 'Stark', firstName: 'Arya', age: 16 },
  { id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null },
  { id: 6, lastName: 'Melisandre', firstName: null, age: 150 },
  { id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 },
  { id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 },
  { id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 },
];

export default function DataGridDemo() {

 const [select, setSelection] = useState([]);

    const handleRowSelection = (e) => {
       
       // prints correct indexes of selected rows
        console.log(e.selectionModel);
        
        // missing the first row selected
        setSelection(e.selectionModel);
        console.log(select);

    }

  return (
    <div style={{ height: 400, width: '100%' }}>
      <DataGrid 
      rows={rows} 
      columns={columns} 
      pageSize={5} 
      checkboxSelection 
      NoRowsOverlay
      onSelectionModelChange = {handleRowSelection}
      />
    </div>
  );
}
1 Answers

Set a state variable is an async method.

This is where useEffect come into the picture. useEffect meant to run side effects when something changed. So

const handleRowSelection = (e) => {
  setSelection(e.selectionModel);
  console.log(select); // <-- The state is still not updated
}

But

const handleRowSelection = (e) => {
  setSelection(e.selectionModel);
}

useEffect(() => {
  console.log(select); // <-- The state is updated
}, [select]);

https://codesandbox.io/s/charming-sutherland-9ryyt

Notice the useEffect callback been called also once the component loaded (because select has been changed) but in this case it doesn't matter because it initiated as an empty array - nothing been selected yet.

Related