React答题按钮优化:点击核对后按正确性切换样式
React答题应用结果样式实现方案
核心思路调整
- 简化状态管理:将分散的
button和disabled状态合并为userAnswers对象,记录每个题目用户选中的答案ID,逻辑更直观易维护。 - 动态生成按钮样式:点击
Check Answers后(即showResults为false时),根据用户选中的答案是否正确,动态添加correct或incorrect类改变背景色。 - 消除代码冗余:通过循环遍历
questions数组渲染所有题目,避免重复编写四次题目代码。
修改后的完整代码
import { useState } from 'react'; function Quiz(props) { const questions = [ { questionText: 'What is the Capital of France?', answerOptions: [ { id: 0, answerText: 'London', isCorrect: false, answer: 0 }, { id: 0, answerText: 'Paris', isCorrect: true, answer: 1 }, { id: 0, answerText: 'Nice', isCorrect: false, answer: 2 }, { id: 0, answerText: 'Lyon', isCorrect: false, answer: 3 }, ], }, { questionText: 'What is the Capital of the UK?', answerOptions: [ { id: 1, answerText: 'London', isCorrect: true, answer: 4 }, { id: 1, answerText: 'New York', isCorrect: false, answer: 5 }, { id: 1, answerText: 'Sydney', isCorrect: false, answer: 6 }, { id: 1, answerText: 'Bath', isCorrect: false, answer: 7 }, ], }, { questionText: 'Who turns out to be the true victor in the Battle of Armageddon in Mortal Kombat?', answerOptions: [ { id: 2, answerText: 'Liu Kang', isCorrect: false, answer: 8 }, { id: 2, answerText: 'Shang Tsung', isCorrect: false, answer: 9 }, { id: 2, answerText: 'Raiden', isCorrect: false, answer: 10 }, { id: 2, answerText: 'Shao Kahn', isCorrect: true, answer: 11 }, ], }, { questionText: 'Under what pseudonym did Stephen King publish five novels between 1977 and 1984?', answerOptions: [ { id: 3, answerText: 'Richard Bachman', isCorrect: true, answer: 12 }, { id: 3, answerText: 'J. D. Robb', isCorrect: false, answer: 13 }, { id: 3, answerText: 'Mark Twain', isCorrect: false, answer: 14 }, { id: 3, answerText: 'Lewis Carroll', isCorrect: false, answer: 15 }, ], }, ]; const [startQuiz, setStartQuiz] = useState(true); const [score, setScore] = useState(0); // 用对象存储用户选择:key是题目id,value是选中的answerId const [userAnswers, setUserAnswers] = useState({}); const [showResults, setShowResults] = useState(true); function startClick() { setStartQuiz(current => !current); } const optionClicked = (questionId, answerId, isCorrect) => { // 记录当前题目选中的答案 setUserAnswers(prev => ({...prev, [questionId]: answerId})); // 仅在首次选中正确答案时加分 if (isCorrect && !userAnswers[questionId]) { setScore(prev => prev + 1); } }; function resultsClick() { setShowResults(current => !current); } function restartQuiz() { setStartQuiz(true); setShowResults(true); setScore(0); setUserAnswers({}); } return ( <div> {startQuiz ? ( <div className="start-screen"> <div className="start-text"> <h1>Quizzical</h1> <p>Test your knowledge!</p> <button onClick={startClick}>Start Quiz</button> </div> </div> ) : ( <div className="quiz"> {/* 循环渲染所有题目,消除冗余 */} {questions.map((question, qIndex) => ( <div key={qIndex} className={`question-${qIndex + 1}`}> <h2>{question.questionText}</h2> <div className={`answers-${qIndex + 1}`}> {question.answerOptions.map(answerOption => { const { id: questionId, isCorrect, answer: answerId, answerText } = answerOption; const isSelected = userAnswers[questionId] === answerId; let buttonClass = "button"; // 动态分配按钮样式类 if (!showResults) { if (isSelected) { buttonClass = isCorrect ? "button correct" : "button incorrect"; } } else if (isSelected) { buttonClass = "buttonClicked"; } return ( <button className={buttonClass} key={answerId} // 题目已有选中答案则禁用所有选项 disabled={!!userAnswers[questionId]} onClick={() => optionClicked(questionId, answerId, isCorrect)} > {answerText} </button> ); })} </div> </div> ))} <br /> <div className="resultsSection"> <button className="button" onClick={resultsClick}> Check Answers! </button> <h3 className="resultsText"> {showResults ? <p>Score:</p> : <p>Score: {score}/4</p>} </h3> <button className="button" onClick={restartQuiz}>Restart Quiz</button> </div> </div> )} </div> ); } export default Quiz;
补充样式(CSS)
需要在样式文件中添加以下类来实现颜色效果:
.buttonClicked { background-color: #e0e0e0; /* 选中后的浅灰背景 */ } .correct { background-color: #a5d6a7; /* 正确答案的绿色背景 */ } .incorrect { background-color: #ef9a9a; /* 错误答案的红色背景 */ }
关键说明
- 状态优化:
userAnswers对象直接记录每个题目的选中状态,替代原来的两个数组,逻辑更简洁。 - 样式逻辑:通过
showResults状态判断,在查看结果时给选中的正确/错误答案分配对应颜色类,未查看结果时保持原选中样式。 - 代码精简:用循环渲染所有题目,后续新增题目只需修改
questions数组,无需重复编写渲染代码。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

