You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中使用useEffect后单选按钮无法取消选中的问题

问题分析与解决

核心问题

  1. 单选框选中状态判断逻辑错误:当前checked属性的写法是只要selectedAnswer不为null就给选项加checked,这不符合单选框的选中逻辑——单选框应该是当前选项的value等于selectedAnswer时才标记为选中。
  2. useEffect依赖错误:依赖写了setNum,但setNum是React内置的状态更新函数,不会变化,导致后续num更新时useEffect触发异常,应该监听num的变化。
  3. 第四个选项的value值写错:第四个Form.Check的value用了questionsJSON.questions[num].answers[0],应该是answers[3],否则会和第一个选项value重复,导致选中状态混乱。

修正后的代码

状态与逻辑部分

const [selectedAnswer, setSelectedAnswer] = useState("");
const [num, setNum] = useState(0);

const randomNumberInRange = (max) => {
    return Math.floor(Math.random() * (max + 1));
};

const onClickPassRadio = (e) => {
    e.preventDefault();
    setNum(randomNumberInRange(10));
};

useEffect(() => {
    setSelectedAnswer(""); // 和初始状态保持一致,用空字符串而非null
}, [num]); // 监听num的变化,而非setNum

表单部分

<Form>
    <ListGroup>
        <ListGroup.Item className="text-start">
            <div>
                <Form.Check
                    type="radio"
                    id="0"
                    name="answer"
                    label={questionsJSON.questions[num].answers[0]}
                    value={questionsJSON.questions[num].answers[0]}
                    onChange={e => setSelectedAnswer(e.target.value)}
                    checked={selectedAnswer === questionsJSON.questions[num].answers[0]}
                />
            </div>
        </ListGroup.Item>
        <ListGroup.Item className="text-start">
            <Form.Check
                type="radio"
                id="1"
                name="answer"
                label={questionsJSON.questions[num].answers[1]}
                value={questionsJSON.questions[num].answers[1]}
                onChange={e => setSelectedAnswer(e.target.value)}
                checked={selectedAnswer === questionsJSON.questions[num].answers[1]}
            />
        </ListGroup.Item>
        <ListGroup.Item className="text-start">
            <Form.Check
                type="radio"
                id="2"
                name="answer"
                label={questionsJSON.questions[num].answers[2]}
                value={questionsJSON.questions[num].answers[2]}
                onChange={e => setSelectedAnswer(e.target.value)}
                checked={selectedAnswer === questionsJSON.questions[num].answers[2]}
            />
        </ListGroup.Item>
        <ListGroup.Item className="text-start">
            <Form.Check
                type="radio"
                id="3"
                name="answer"
                label={questionsJSON.questions[num].answers[3]}
                value={questionsJSON.questions[num].answers[3]} {/* 修正此处value */}
                onChange={e => setSelectedAnswer(e.target.value)}
                checked={selectedAnswer === questionsJSON.questions[num].answers[3]}
            />
        </ListGroup.Item>
    </ListGroup>
    <br />
    <Button variant="danger" onClick={onClickPassRadio}>submit</Button>
</Form>

额外优化建议

可以通过循环渲染选项减少冗余代码,适配任意数量的选项:

<Form>
    <ListGroup>
        {questionsJSON.questions[num].answers.map((answer, index) => (
            <ListGroup.Item key={index} className="text-start">
                <Form.Check
                    type="radio"
                    id={String(index)}
                    name="answer"
                    label={answer}
                    value={answer}
                    onChange={e => setSelectedAnswer(e.target.value)}
                    checked={selectedAnswer === answer}
                />
            </ListGroup.Item>
        ))}
    </ListGroup>
    <br />
    <Button variant="danger" onClick={onClickPassRadio}>submit</Button>
</Form>

内容的提问来源于stack exchange,提问作者Keshav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:38:30