Home > front end >  Selecting and deseleting all checkboxes using hooks
Selecting and deseleting all checkboxes using hooks

Time:10-14

I have an array state for some checkboxes where I am catching the labels for those that are true (checked). Must ignore the false.

I am able to generate a list of checked checkboxes thanks to some of you in another thread. But I'm hitting another wall with the select all toggle.

  const handleSwitch = (e) => {
    if(e.target.checked) {
      setActive(true);
      const updatedCheckedState = checkedState.map(element => element.checked = true);
      setCheckedState([...updatedCheckedState]);   
    } else {      
      setActive(false)
      const updatedCheckedState = checkedState.map(element => element.checked = false);
      setCheckedState([...updatedCheckedState]);   
    }
  }

This function above in particular. Likewise, if I manually check all of the checkboxes inside, it needs to know that all are selescted and make the active state = true. If I can get help with at least the first part, I'm confident I can solve the other part myself.

Here's a sandbox if you want to mess around with it. Thanks

CodePudding user response:

Your sandbox is quite broken. The way you are tracking checked state is internally inconsistent.)

The main culprits (in Filter.js) are:

  • on line 119, you treat checkedState like a dictionary, but in handleSwitch and handleOnChange you treat it like an array (but the logic inside is still non-functional for the array approach as far as I can tell.
    • if you want it to be an array, let it be a string-valued "checkedLabels" array, and set checked on your checkbox component to checkedLabels.includes(item.label)
    • if you want it to be a dictionary:
      • handleOnChange needs to simply toggle the currently clicked element, like so [e.target.name]: !checkedState[e.target.name]
      • handleSwitch needs to add an entry for every element in data, set to true or false as appropriate.

Example (codesandbox):

const handleSwitch = (e) => {
  if (e.target.checked) {
    setActive(true);
    setCheckedState(
      Object.fromEntries(data.map((item) => [item.label.toLowerCase(), true]))
    );
  } else {
    setActive(false);
    setCheckedState({});
  }
};

const handleOnChange = (e) => {
  setCheckedState({
    ...checkedState,
    [e.target.name]: !checkedState[e.target.name]
  });
};

<CustomCheckbox
  size="small"
  name={item.label.toLowerCase()}
  checked={checkedState[item.label.toLowerCase()] ?? false}
  onChange={handleOnChange}
/>

CodePudding user response:

Adding to @JohnPaulR answer. You can add useEffect hoot to achieve additional requirements you have.

if I manually check all of the checkboxes inside, it needs to know that all are selected and make the active state = true.

  useEffect(() => {
    const checkedTotal = Object.keys(checkedState).reduce((count, key) => {
      if (checkedState[key]) {
        return count   1;
      }
    }, 0);
    setActive(data.length === checkedTotal);
  }, [checkedState]);

A full working example https://codesandbox.io/s/still-water-btyoly

  • Related