如何使用 Formik 更改一组复选框的 UI 状态

How to change the UI state of a group of Checkboxes with Formik

我有一系列复选框需要在单击时更改它们的 UI。例如,如果第一个复选框被点击,它应该独立于其他复选框改变颜色。

这是我目前的工作,但它像单选按钮一样工作,因为一次只选中一个复选框。

function RecordGame() {
const [checkedStatus, setCheckedStatus] = useState(members.map(() => false))

  const handleSetChecked = async (index) => {
    let newState = members.map(() => false)
    console.log(newState)
    newState[index] = true
    setCheckedStatus(newState)
  }

  
const playerCheckboxes = members.map((player, index) => {
  return (
    <div key={index} className="flex gap-2">
      <label htmlFor={player.name}>
        <Field
          checked
          type="checkbox"
          onClick={() => handleSetChecked(index)}
          id={player.name}
          name="players"
          value={player.name}
        />
        <span
          // Change the checkbox UI based on the checkedStatus
          className={`${checkedStatus[index] ? 'bg-quad text-primary' : 'bg-transparent'}`}
        >
          {player.name}
        </span>
      </label>
    </div>
  )
})

return( {playerCheckboxes} }

问题是 handleSetChecked 被调用,下面的代码行总是将数组中所有项目的 checkedStatus 重置为 unchecked

let newState = members.map(() => false)

在同一函数中的这一行 newState[index] = true 导致复选框表现为 radio 按钮,因为对于特定索引,它始终将状态设置为 checked

要解决此问题,您需要更新 handleSetChecked 函数,这样它就不会重置 checkedStatus 并处理同一索引的先前值来处理检查和取消检查复选框的状态。

const handleSetChecked = async (index) => {
  let newState = [...checkedStatus] // make a copy of the current state of the checkedStatus
  newState[index] = !checkedStatus[index] // update the relevant index based on the previous state. If its checked, uncheck it and vice versa.
  setCheckedStatus(newState)
}