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
相关产品推荐
相关产品推荐

