0

I have a table of data. The first column is a Checkbox. I'm trying to create an array of each row id that gets selected.

  const [selectedRows, setSelectedRows] = useState([]);

  const handleCheckbox = (event, row) => {
    if (event.target.checked === true) {
      selectedRows.push(row.id);
    } else {
      selectedRows.pop(row.id);
    }
  };

        <TableBody>
            {expenseTransactions.map((row) => (
              <TableRow key={row.id}>
                <TableCell>
                  <Checkbox onChange={(event) => handleCheckbox(event, row)} />
                </TableCell>
              </TableRow>
       </TableBody>

I can't get it to work properly. Any ideas on the best way to handle the onChange event so I have an array of all selected elements, and then if i unselect one, that id would get removed from the array.

Thanks a tonne,

3 Answers 3

1

You should not change the state directly by using selectedRows.push(). The right way is using setSelectedRows. The proper code will look like this.

const handleCheckbox = (event, row) => {
  if (event.target.checked === true) {
    setSelectedRows([
       ...selectedRows,
       row
    ])
  } else {
    const nextSelectedRows = selectedRows.filter(selectedRow => selectedRow.id != row.id);
    setSelectedRows(nextSelectedRows)
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

When I deal with that scenario I prefer to store the checked elements into an object, using that approach you avoid finding the index affected. Moreover, the Material UI's Checkbox has to be set with its checked prop.

e.g:

 const [selectedRows, setSelectedRows] = useState({});

the handler:

 const handleCheckbox = (event, row) => {
      setSelectedRows((state) => 
         ({ 
           ...state, 
           selectedRows: { 
             ...state.selectedRows, 
             [row.id]: event.target.checked
           } 
         })
       );
 };

the JSX:

 <TableBody>
        {expenseTransactions.map((row) => (
          <TableRow key={row.id}>
            <TableCell>
              <Checkbox 
                checked={ selectedRows[row.id] || false } 
                onChange={(event) => handleCheckbox(event, row)} 
              />
            </TableCell>
          </TableRow>
   </TableBody>

Comments

0

to maintain the checked state in a state, store the checked items' names in the array.

  const [checkedState, setChekcedState] = useState([]);
  
  const handleChange = (e) =>{
    const {checked, name} = e.target
    if(checked){
      setChekcedState(oldState => ([...oldState, name]))
    }else{
      setChekcedState(oldState => oldState.filter(item => item !== name))
    }
  }

as per the comment, ids are the numbers. So, convert the number into a string.
And when the array is required, convert those strings back to the number.

<TableBody>
    {expenseTransactions.map((item) => (
        <TableRow key={item.id}>
            <Checkbox
                onChange={handleChange}
                checked={checkedState.includes(item.id)}
                name={item.id}
            />
        </TableRow>
    ))}
</TableBody>

Converting those string back into numbers

let convertedIntegerArr = checkedState.map(item=>parseInt(item))

Here is the working demo
Edit thirsty-sun-d1zy9

2 Comments

Thanks for this. One thing, my ids are numbers which is causing this not to work. How would you solve for that? Cheers
hi! for this one simple and straightforward solution is to convert that number into a string. I'm updating my answer accordingly

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.