2

I know this question has been asked before but I have an array I'm looping over the array getting data from that array and displaying that data in a list and in that list I have checkbox I want to get some data when the checkbox is ticked and store in a state array

this is my code so far, the issue that I am having now is that the first click on the first checkbox registers as an empty array and the consecutive clicks after store the values in the array I think that us due to the fact that useState is set to empty how can I change the code so that I store the values of the checkbox in an array to be used later


    const [checkList, setCheckList] = useState([]);
    
    const handleChange = e => {
        setCheckList([...checkList, e]);
        setChecked(prev => !prev);
        console.log(checkList);
      };


    <List>
          {someList.map(w => (
            <ListItem key={w.id}>
              <ListItemIcon>
                <ReactSVG
                  style={{ height: '35px', width: '35px' }}
                  src={w.logo}
                />
              </ListItemIcon>
              <ListItemText primary={w.name} />
              <ListItemSecondaryAction>
                <Checkbox
                  edge="end"
                  onChange={e => handleChange(e.target.value)}
                  value={w.id}
                  // checked={checked}
                />
              </ListItemSecondaryAction>
            </ListItem>
          ))}
        </List>
    
Asker
  • 97
  • 1
  • 11
  • Its slightly easier to answer your question if you add a link to your sandbox – vinayak shahdeo Jul 14 '20 at 08:17
  • How are you so sure that the first click is registering empty array, is it because of the console? May be this solves your confusion https://stackoverflow.com/questions/62846824/react-select-onchange-returning-previous-value-instead-of-current/62846909#62846909 – Rohan Agarwal Jul 14 '20 at 08:21
  • yh because of the console and i cooked up this hope it helps https://codesandbox.io/s/silent-framework-gczuz?file=/src/App.js – Asker Jul 14 '20 at 08:31
  • If you move the console.log statement out of your function and into the render you will see that it is working as you want it to. It's just that the checkList variable is read before setChecklist is run. Take a look athttps://codesandbox.io/s/great-darkness-iry75?fontsize=14&hidenavigation=1&theme=dark – Zayco Jul 14 '20 at 08:38
  • Do you get the `someList` from props? I'm asking bcuz I want to suggest an optimal solution. – Sultan H. Jul 14 '20 at 08:41
  • @Asker did you checked my solution, i hope it will solve your issue – mohit uprim Jul 15 '20 at 09:18
  • @mohituprim yh i did and i used it to implement my own version of it but you really did give me a boost thank you – Asker Jul 21 '20 at 14:23

1 Answers1

2

Checked should be determined based on checkList items. and handleChange should update the state depending on the checked value of the checkbox. Check my solution.

export default function App() {
  const [checkList, setCheckList] = useState([]);

  const workspaces = [
    {
      id: 1,
      name: "hello"
    },
    {
      id: 2,
      name: "hello2"
    }
  ];
  const handleChange = e => {

    if (e.target.checked === true) {
      setCheckList([...checkList, Number(e.target.value)]);
    } else {
      const selectedAcc = checkList.filter(a => {
        if (a === Number(e.target.value)) return false;
        return true;
      });
      setCheckList([...selectedAcc]);
    }
  };

  return (
    <div className="App">
      <List>
        {workspaces.map(w => (
          <ListItem key={w.id}>
            <ListItemText primary={w.id} />
            <ListItemSecondaryAction>
              <Checkbox
                edge="end"
                onChange={e => handleChange(e)}
                value={w.id}
                checked={
                  checkList.lastIndexOf(Number(w.id)) >= 0 ? true : false
                }
              />
            </ListItemSecondaryAction>
          </ListItem>
        ))}
      </List>
    </div>
  );
}
mohit uprim
  • 5,226
  • 2
  • 24
  • 28