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

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; /* 错误答案的红色背景 */
}

关键说明

  1. 状态优化:userAnswers对象直接记录每个题目的选中状态,替代原来的两个数组,逻辑更简洁。
  2. 样式逻辑:通过showResults状态判断,在查看结果时给选中的正确/错误答案分配对应颜色类,未查看结果时保持原选中样式。
  3. 代码精简:用循环渲染所有题目,后续新增题目只需修改questions数组,无需重复编写渲染代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:10:01