复选框未取消选中 React

Checkbox not unchecking with React

我有一组匹配项,在我的 React 应用程序中显示为行列表。每行有两名运动员,您可以使用复选框来预测哪一个会获胜。每行只能检查一名运动员,所以我做了类似以下的操作来存储谁被检查,谁没有:

在初始安装时,我有一个空的 object 处于名为 predictions 的状态。当用户开始与复选框交互时,我使用每行的索引作为键来存储其中一名运动员的 ID。这就是它在实践中的样子,

{
  0: '12864',
  3: '13333',
  5: '45362',
  ...etc
}

所以你可以更好地了解我在做什么,这是一个屏幕截图。

在我的 React 代码中,我通过匹配数组进行映射,如下所示:

<ul>
{matches &&
    matches.map((match, i) => (
    <li
        key={match.fighter_a_name + match.fighter_b_name}
        className="text-center"
    >
        <Row>
        <Col md={5}>
            <h3>
            {match.fighter_a_name}
            </h3>

            <FormCheck
            type="checkbox"
            id={match.fighter_a_id}
            idx={i}
            onChange={handlePrediction}
            checked={
                parseInt(predictions[i]) === match.fighter_a_id ||
                false
            }
            />
        </Col>

        <Col md={2}>
            {/* <div>{match.weight}</div>
            <div>{match.result}</div>
            <div>{match.time}</div> */}
            <div>{match.rounds}</div>
        </Col>

        <Col md={5}>
            <h3>
            {match.fighter_b_name}
            </h3>

            <FormCheck
            id={match.fighter_b_id}
            idx={i}
            onChange={handlePrediction}
            checked={
                parseInt(predictions[i]) === match.fighter_b_id ||
                false
            }
            />
        </Col>
        </Row>
    </li>
    ))}
</ul>

每次单击复选框都会执行名为 handlePrediction 的函数,该函数处理更新预测的逻辑 object。它主要检查它们当前是否是 object 中的键,其 id 值与刚刚单击的复选框相同。如果是这样,它将从 object 中删除该键,否则,它只是将该键添加到 object,或覆盖该键的当前 ID。

我想我这里可能有一些逻辑问题,但现在,就是这样了。

const handlePrediction = (e) => {
    const id = e.target.id;
    const idx = e.target.getAttribute("idx");

    if (predictions[idx] === id) {
        setPredictions((prev) => {
        delete prev[idx];
        return prev;
        });
    } else {
        setPredictions((prev) => ({ ...prev, [idx]: id }));
    }
};

既然我给了你背景故事,我遇到的问题是我无法取消选中特定场景中的运动员。如果我检查一行中的运动员,他们的 id 将成功添加到 object。然后,如果我勾选同一行的另一个运动员,前一个运动员变成未勾选,而刚刚点击的运动员变成勾选,这就是我想要的。

但是,如果我选中一名运动员,然后尝试取消选中他们,则该复选框会永久保持选中状态。每次单击时,handlePrediction 函数似乎都能正确处理所有内容,adds/removes 来自 object 的用户,但复选框没有任何变化。

我不知道为什么复选框不会取消选中。我创建了一个 slimmed down version of this code in a Codepen,您可以对其进行修改,它具有完整的匹配数据数组,因此您也可以看到它的样子。

P.S. 我还发现了其他问题。如果您使用代码笔,请执行以下操作:

  1. 检查肖恩·斯特里克兰
  2. 检查 Cheyanne Buys
  3. 检查肖恩·斯特里克兰
  4. 检查 Cheyanne Buys
  5. 检查肖恩·斯特里克兰

在第 5 步之后,您应该会看到 Cheyanne Buys 未被选中,这是不应该发生的。我这里肯定做错了什么。

因为你改变了原始状态,所以即使你设置状态,看起来你也为当前状态设置了相同的值

您可以尝试克隆原始对象,并改变复制对象和return它

代码如下:

const handlePrediction = (e) => {
    const id = e.target.id;
    const idx = e.target.getAttribute("idx");

    if (predictions[idx] === id) {
        setPredictions((prev) => {
          // clone a new object
          const newPrediction = { ...prev };
          delete newPrediction [idx];
          return newPrediction;
        });
    } else {
        setPredictions((prev) => ({ ...prev, [idx]: id }));
    }
};