首页 > 解决方案 > 如何在 React 中控制多个复选框?

问题描述

我在一个组件中有一个主复选框和其他多个复选框

代码:

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>
  )
};

如您所见,主复选框和其他复选框由单独的状态和单独的onChange功能控制。一切正常,但有一个误解的时刻。如果我选中主复选框,则所有其他复选框都会被选中。如果我取消选中任何其他复选框,我需要取消选中我的主复选框。相反,如果我的所有其他复选框都被选中,我还需要选中我的主复选框。

在我的情况下我怎么能做到这一点?

标签: javascriptreactjscheckboxuse-state

解决方案


更改复选框时,如果未选中任何内容或现在全部选中,则不会更新主复选框。

在您的方法checkBoxChange中,您必须验证两种状态:

  1. 如果在 4 个复选框中未选中任何内容 - 也取消选中主复选框。

  2. 如果 3 个复选框被选中,并且您碰巧将第四个复选框选中以进行全面检查 - 更新主复选框并选中。


推荐阅读