Home > Blockchain >  How to work with multiple checkboxes in react and collect the checked checkboxes
How to work with multiple checkboxes in react and collect the checked checkboxes

Time:09-16

I'm currently working on a filter component where multiple checkboxes can be selected.

Now I want to toggle the state of the checkboxes (which is currently possible and works) and store the checked checkboxes in an array.

If a checkbox is unchecked, it should of course be removed from the array. I've tried the useState hook, but without success --> The checkboxes are added multiple times and the unchecked ones are not removed..

Here is the current status:

  // Here I'm creating an array with a fixed size (based on the received data)
  const [checkboxState, setCheckboxState] = useState(new Array(receivedData.length).fill(false));
  // With this useState I wan't to collect the checked checkboxes
  const [checkedCheckboxes, setCheckedCheckboxes] = useState([]);
    
  // This is my handler method that gets triggered when a checkbox get's checked/unchecked
  // ..and toggles the state of the checkbox
  const handleCheckboxState = (position: number) => {
    const updatedCheckedState = checkboxState.map((item, index) => (index === position ? !item : item));
    setCheckboxState(updatedCheckedState);
    collectCheckedCheckboxes();
  };

  // With this method I wan't to push the checked checkboxes into the array
  // ..and remove the unchecked ones
  const collectCheckedCheckboxes = () => {
    checkboxState.map((item, index) => {
      if (item === true) {
        return checkedCheckboxes.push(receivedData[index]);
      } else {
        return checkedCheckboxes.slice(index, 1);
      }
    });
  };

The checkboxes are rendered like this:

  <div className="checkboxes">
    {receivedData?.map((data, index) => (
      <CheckBox
        value={data.value}
        checked={checkboxState[index]}
        onChange={() => handleCheckboxState(index)}
      />
    ))}
  </div>

What am I doing wrong?

CodePudding user response:

Your CheckBox-component does not contain a key property. This is helpful for React to identify which items have changed, are added, or are removed.

Source: https://reactjs.org/docs/lists-and-keys.html

I also do not understand why you have two states, checkboxState and checkedCheckboxes. Is there another reason for this? I think this would be easier with a single state which holds the indexes (or values) of the checked checkboxes.

[update after comments]

The code below is the desired solution by OP to have the selected object values in a React state.

const { useState } = React;

const Checkboxes = () => {
  // With this useState I wan't to collect the checked checkboxes
  const [checkedCheckboxes, setCheckedCheckboxes] = useState([]);

  // This is my handler method that gets triggered when a checkbox get's checked/unchecked
  // ..and toggles the state of the checkbox
  const handleCheckboxChange = (data) => {
    const isChecked = checkedCheckboxes.some(checkedCheckbox => checkedCheckbox.value === data.value)
    if (isChecked) {
      setCheckedCheckboxes(
        checkedCheckboxes.filter(
          (checkedCheckbox) => checkedCheckbox.value !== data.value
        )
      );
    } else {
      setCheckedCheckboxes(checkedCheckboxes.concat(data));
    }
  };

  const receivedData = [{ value: "A" }, { value: "B" }, { value: "C" }];

  return (
    <>
      <div className="checkboxes">
        <h1>Checkboxes:</h1>
        {receivedData?.map((data, index) => (
          <input
            key={`cb-${index}`}
            value={data.value}
            type="checkbox"
            checked={checkedCheckboxes.some(checkedCheckbox => checkedCheckbox.value === data.value)}
            onChange={() => handleCheckboxChange(data)}
          />
        ))}
      </div>
      <div>
        <h1>State:</h1>
        <pre>{JSON.stringify(checkedCheckboxes, null, 2)}</pre>
      </div>
    </>
  );
};

ReactDOM.render(<Checkboxes />, document.getElementById("app"));
  • Related