vendredi 8 janvier 2021

How do I control multiple checkboxes in React?

I have a main checkbox and other multiple checkboxes in a component

Code:

const Filter = () => {

  const [checkBoxes, setCheckBoxes] = useState([
    {id: 'without', label: "Без пересадок", isChecked: true},
    {id: 'one', label: "1 пересадка", isChecked: true},
    {id: 'two', label: "2 пересадки", isChecked: true},
    {id: 'three', label: "3 пересадки", isChecked: true}
  ])

  const [mainCheckbox, setMainCheckbox] = useState({
    id: 'all', label: "Все", isChecked: true
  })

  const allCheckBoxesChange = ({ target : { checked } }) => {
    setMainCheckbox({
      ...mainCheckbox,
      isChecked: checked
    })
    let allCheckBoxes = [...checkBoxes]
    allCheckBoxes.forEach(item => {
      item.isChecked = checked
    })
    setCheckBoxes(allCheckBoxes)
  }

  const checkBoxChange = ({ target : { name, checked } }) => {
    let newCheckBoxes = [...checkBoxes]
    newCheckBoxes.forEach(item => {
      if (item.id === name) {
        item.isChecked = checked
      }
    }) 
    setCheckBoxes(newCheckBoxes)
  }

  return (
    <div className="content__filter">
      <div className="content__filter__name">
        Количество пересадок
      </div>
      <div className="content__filter__list">
        <div className="content__filter__item">
          <input 
            type="checkbox" 
            id={mainCheckbox.id} 
            name={mainCheckbox.id}
            checked={mainCheckbox.isChecked} 
            onChange={allCheckBoxesChange}
          />
          <label htmlFor={mainCheckbox.id}>{mainCheckbox.label}</label>
        </div>
        <ul>
          {checkBoxes.map(item => (
            <CheckBox 
              key={item.id}
              id={item.id}
              name={item.id} 
              htmlFor={item.id} 
              label={item.label}
              checked={item.isChecked}
              onChange={checkBoxChange}
            />
          ))}
        </ul>
      </div>
    </div>
  );
};

const CheckBox = ({ 
  type = "checkbox", 
  name, 
  htmlFor, 
  label, 
  onChange, 
  checked, 
  id,
}) => {
  return (
    <div className="content__filter__item">
      <input 
        type={type} 
        id={id} 
        name={name} 
        checked={checked} 
        onChange={onChange}
      />
      <label htmlFor={htmlFor}>{label}</label>
    </div>
  )
};

As you can see a main checkbox and other checkboxes are controlled by separate states and separate onChange functions. Everything works good but there is a misunderstanding moment. If I check main checkbox, all other checkboxes become checked. If I uncheck any other checkbox I need to uncheck my main checkbox. And the opposite, if my all other checkboxes are checked I need my main checkbox to be checked also.

How I can do that in my case?




Aucun commentaire:

Enregistrer un commentaire