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

React中用单选按钮切换答题正误提示的问题求助

测验应用问题排查与修复

我正在开发一个小型测验应用,需求是在题目下方切换提示消息,告知用户所选答案正确或错误。目前通过布尔值isCorrect控制消息显示,该值由单选按钮的选择状态设置,但存在以下问题:

  • 首次点击正确选项时,单选按钮未被选中,仅错误选项可正常选中;
  • 选中错误选项时无法显示“错误”提示,仅能在选中正确选项时显示“You got it right!”;
  • 点击“Next question”按钮后提示消息未被清除。

相关代码:

function App() {
  let [points, setPoints] = useState(null);
  let [counter, setCounter] = useState(null);
  let [question, setQuestions] = useState();
  let [isCorrect, setIsCorrect] = useState(false); // Store correct answer selected
  
  function Answer(props) {
    return (
      <li aria-labelledby="answers-list">
        <label>
          <input
            type="radio"
            name="answer_group"
            className="answer"
            value={props.answer}
            onChange={checkAnswer}
          />
          {props.answer}
        </label>
      </li>
    );
  }

  function checkAnswer(e) {
    let val = e.target.value;
    let ans = question[counter].answers.filter((ans) => ans.value === val)[0];
    displayCorrect(ans.correct);
    // Toggles message to true if answer is correct
    ans.correct === true ? setIsCorrect(true) : setIsCorrect(false);
  }

  function Quiz(props) {
    return (
      <div className="quiz">
        <div className="quesiton" role="h2">
          {props.question}
        </div>
        <ul className="answers">{props.children}</ul>
      </div>
    );
  }

  function displayCorrect(correct) {
    let correct_msg = correct ? "correct" : "incorrect";
    console.log("Answer was " + correct_msg);
  }

  function nextQuestion() {
    setIsCorrect(false); // Should hide message when user selects "next question" button
    if (document.querySelector('input[name="answer_group"]:checked') == null) {
      alert("Must select an answer before proceeding to the next question");
      return;
    }
    let val = document.querySelector('input[name="answer_group"]:checked')
      .value;
    let answerObj = question[counter].answers.filter(
      (ans) => ans.value === val
    )[0];
    let updated_points = answerObj.correct ? points + 1 : points;
    setPoints(updated_points);
    let nextQuestion = counter + 1;
    if (counter < question.length - 1) {
      setCounter(nextQuestion);
    } else {
      setCounter(0);
    }
    displayCorrect(answerObj.correct);
  }
  
  return (
    <div className="Quiz slide-top">
      {!is_started ? (
        <div className="start-intro-wrapper">
          <h1 className="name">Quiz App</h1>
          <Starter start={start} />
        </div>
      ) : (
        <div className="quick-wrapper slide-in-bottom">
          <Quiz question={question[counter].question}>
            {question[counter].answers.map((answer, index, arr) => {
              return (
                <Answer
                  key={index}
                  index={index}
                  answer={answer.value}
                  correct={answer.correct}
                />
              );
            })}
          </Quiz>
          <div className="answer-controls">
            {isCorrect === true ? <p>You got it right!</p> : null} {/* Messaging should show if user has selected correct message if correct option is selected */}
            <button onClick={(e) => nextQuestion()}>
              Next question
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

问题修复方案

1. 解决正确选项无法选中的问题

核心问题是单选按钮未做受控绑定,且依赖DOM查询状态不可靠。新增状态跟踪选中选项,绑定到单选按钮的checked属性:

  • 新增selectedAnswer状态:
    let [selectedAnswer, setSelectedAnswer] = useState(null);
    
  • 修改Answer组件的input,添加受控绑定:
    <input
      type="radio"
      name="answer_group"
      className="answer"
      value={props.answer}
      onChange={checkAnswer}
      checked={selectedAnswer === props.answer}
    />
    
  • 在checkAnswer中更新选中状态:
    function checkAnswer(e) {
      let val = e.target.value;
      setSelectedAnswer(val); // 新增:更新选中状态
      let ans = question[counter].answers.filter((ans) => ans.value === val)[0];
      displayCorrect(ans.correct);
      setIsCorrect(ans.correct);
    }
    

2. 解决错误提示不显示的问题

当前仅渲染正确提示,补充错误提示的渲染逻辑,同时避免初始状态下显示错误提示:

<div className="answer-controls">
  {isCorrect === true && <p>You got it right!</p>}
  {isCorrect === false && selectedAnswer !== null && <p>That's wrong!</p>}
  <button onClick={(e) => nextQuestion()}>
    Next question
  </button>
</div>

3. 解决切换题目后提示未清除的问题

在nextQuestion中同时重置选中状态和提示状态,并改用状态判断替代DOM查询:

function nextQuestion() {
  setIsCorrect(false);
  setSelectedAnswer(null); // 新增:重置选中状态
  if (!selectedAnswer) { // 改用状态判断,避免DOM查询
    alert("Must select an answer before proceeding to the next question");
    return;
  }
  // 改用selectedAnswer获取选中值,不再操作DOM
  let answerObj = question[counter].answers.filter(
    (ans) => ans.value === selectedAnswer
  )[0];
  let updated_points = answerObj.correct ? points + 1 : points;
  setPoints(updated_points);
  let nextQuestion = counter + 1;
  if (counter < question.length - 1) {
    setCounter(nextQuestion);
  } else {
    setCounter(0);
  }
  displayCorrect(answerObj.correct);
}

额外优化:初始化状态修正

给points和counter设置初始值0,避免null带来的潜在问题:

let [points, setPoints] = useState(0);
let [counter, setCounter] = useState(0);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 17:39:19