Uncheck multiple checkboxes in checkbox group using React hooks
P粉008829791
P粉008829791 2023-08-30 13:23:32
0
2
533
<p>I ran several checkboxes in several checkbox groups. I can't figure out how to uncheck (thereby changing the state) a specific checkbox. For some reason I can't access <code>e.target.checked</code>. </p> <pre class="brush:php;toolbar:false;"><Checkbox size="small" name={item} value={item} checked={checkboxvalues.includes(item)} onChange={(e) => handleOnChange(e)} /></pre> <p>and my functions</p> <pre class="brush:php;toolbar:false;">const handleOnChange = (e) => { const check = e.target.checked; setChecked(!check); };</pre> <p>I made a working example of the component in <strong>this sandbox</strong>. </p>
P粉008829791
P粉008829791

reply all(2)
P粉322319601

Here's how I did it: https://codesandbox.io/s/elastic-pateu-flwqvp?file=/components/Selectors.js

I abstracted the selection logic into a useSelection() custom hook, which means the current selection can be found in store[key].selected, where key can be any key of selectors.

items, selected, setSelected and sectionLabel are stored in each useSelection() call In store[key], and passed to a <CustomCheckboxGroup /> component.

The relevant part is the handleCheck function within this component, which sets the new selection based on the previously selected value: if the current item is contained within the previously selected value, remove it. Otherwise, add it.


More detailed explanation (why)

Looking closely at your code, it seems like you are confused about how the checkbox component works in React.

The

checked attribute of input is controlled by a boolean state. Generic example:

const Checkbox = ({ label }) => {
  const [checked, setChecked] = useState(false)
  return (
    <label>
      <input
        type="checkbox"
        checked={checked}
        onChange={() => setChecked(!checked)}
      />
      <span>{label}</span>
    </label>
  )
}

On each render, the checked value of <input /> is set based on the current value of the checked state. When the entered checked changes (during user interaction), the status is not automatically updated. But the onChange event is fired and we use it to update the state to the negative value of the state's previous value.


When dealing with the <CheckboxList /> component, we cannot use a single boolean value to control all checkboxes , we need to set a boolean value for each checkbox being rendered. So we create a selected array and set the checked value of each <input /> to selected.includes(item) The value of (returns a boolean).

In order for this to work, we need to update the value of the

selected array in every onChange event. We check if item is contained in the previous version of selected. If present, filter it out. If it doesn't exist, add it:

const CheckboxList = ({ items }) => {
  const [selected, setSelected] = useState([])
  const onChecked = (item) =>
    setSelected((prev) =>
      prev.includes(item)
        ? prev.filter((val) => val !== item)
        : [...prev, item]
    )

  return items.map((item) => (
    <label key={item}>
      <input
        type="checkbox"
        checked={selected.includes(item)}
        onChange={() => onChecked(item)}
      />
      <span>{item}</span>
    </label>
  ))
}
Hope this solves some problems.

P粉060528326

You need to create specific handleOnChange function for each group. I have created a similar function for the Genre checkbox group and you can create it for other groups in the same way.

This is the processing function.

const handleOnChangeGenre = (e) => {
    let newValArr = [];
    if (e.target.checked) {
      newValArr = [...state.pillarGenre.split(","), e.target.value];
    } else {
      newValArr = state.pillarGenre
        .split(",")
        .filter((theGenre) => theGenre.trim() !== e.target.value);
    }
    setState({ ...state, pillarGenre: newValArr.join(",") });
  };

Pass this function to CustomCheckboxGroup as the handleOnChange attribute as shown below.

<CustomCheckboxGroup
          checkboxdata={genres}
          checkboxvalues={state.pillarGenre}
          value={state.pillarGenre}
          sectionlabel="Genre"
          onToggleChange={handleGenreSwitch}
          togglechecked={genreswitch}
          handleOnChange={handleOnChangeGenre}
        />

For testing, comment out your handleOnChange function.

See the complete working solution in the sandbox - Complete code

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template