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

如何为Quiz应用设置统一提交按钮,替代每题单独判分?

实现统一判分的修改方案

要实现所有题目选完后统一判分,需要把选中状态和结果展示的控制权从单个Question组件转移到App组件,让App统一管理所有题目的选择和结果展示逻辑。具体修改步骤如下:

1. 修改App.js,统一管理状态与结果计算

  • 新增userAnswers状态,存储每道题的选中答案
  • 新增showResults状态,控制是否展示判分结果
  • 给Question组件传递选中答案、选择回调、是否显示结果的props
  • 完善checkResult函数,计算得分并触发结果展示

修改后的App.js代码:

import { React, useState, useEffect } from 'react'
import './App.css';
import Question from './components/Question'

function App(){
  const [getQuestions, setGetQuestions] = useState([])
  const [start, setStart] = useState(false)
  // 存储用户每道题的选中答案,key为题目内容,value为选中的选项
  const [userAnswers, setUserAnswers] = useState({})
  // 控制是否显示判分结果
  const [showResults, setShowResults] = useState(false)

  useEffect(function(){
    async function getQuestionsFromApi(){
      const res = await fetch(`https://opentdb.com/api.php?amount=5`)
      const data = await res.json()
      setGetQuestions(data.results)
    }
    getQuestionsFromApi()
  },[])

  // 处理用户选择答案的回调函数
  const handleAnswerSelect = (question, selectedOption) => {
    setUserAnswers(prev => ({
      ...prev,
      [question]: selectedOption
    }))
  }

  const displayQuestions = getQuestions.map(
    element => <Question 
      key={element.question}
      question={element.question}
      correct_answer={element.correct_answer}
      incorrect_answers={element.incorrect_answers}
      // 传递当前题目的选中答案
      selectedOption={userAnswers[element.question]}
      // 传递选择答案的回调
      onSelect={handleAnswerSelect}
      // 传递是否显示结果的状态
      showResults={showResults}
    />
  )

  function gameStart(){
    setStart(true)
    // 开始游戏时重置状态
    setUserAnswers({})
    setShowResults(false)
  }

  function checkResult(){
    // 计算答对的题目数量
    const correctCount = getQuestions.filter(
      q => userAnswers[q.question] === q.correct_answer
    ).length
    console.log(`你答对了${correctCount}/${getQuestions.length}题`)
    // 触发结果展示
    setShowResults(true)
  }

  // 检查是否所有题目都已作答
  const allAnswered = getQuestions.every(q => userAnswers.hasOwnProperty(q.question))

  return(
    <>
      {start ? 
        <div>
          {displayQuestions}
          {/* 只有所有题目都作答后才启用按钮 */}
          <button 
            className='result--button' 
            onClick={checkResult}
            disabled={!allAnswered}
          >
            Check the Answers
          </button>
          {/* 显示得分结果 */}
          {showResults && (
            <div className="score">
              你答对了 {getQuestions.filter(q => userAnswers[q.question] === q.correct_answer).length} / {getQuestions.length} 题
            </div>
          )}
        </div> : 
        <div className="home--page">
          <h1>Quizzical</h1>
          <p>some description if needed</p>
          <button className='start' onClick={gameStart} >Start quiz</button>
        </div>
      }
    </>
  )
}
export default App

2. 修改Question.js,依赖父组件传递的props

  • 移除组件内部的selectedOption状态,改用父组件传递的同名props
  • 修改handleSelect函数,仅在showResults为true时判断对错样式
  • 修改点击事件,调用父组件传递的onSelect回调
  • 调整按钮禁用逻辑:未显示结果时,选中后禁用;显示结果时全部禁用

修改后的Question.js代码:

import { React, useState, useEffect } from 'react'
import './Question.css'

function Question({question, correct_answer, incorrect_answers, selectedOption, onSelect, showResults}){
  const [options, setOptions] = useState([])

  useEffect(function(){
    const arr = [...incorrect_answers, correct_answer]
    // 随机打乱选项顺序(可选优化,避免正确答案固定位置)
    arr.sort(() => Math.random() - 0.5)
    setOptions(arr)
  }, [incorrect_answers, correct_answer])

  function handleSelect(element){
    if (!showResults) {
      // 未显示结果时,只高亮选中的选项
      return selectedOption === element ? 'selected' : ''
    } else {
      // 显示结果时,区分正确/错误/未选中
      if (element === correct_answer) {
        return 'select'
      } else if (selectedOption === element) {
        return 'wrong'
      } else {
        return 'grey'
      }
    }
  }

  function handleClick(element){
    // 调用父组件的回调,传递题目和选中选项
    onSelect(question, element)
  }

  const displayOptions = options.map(element => 
    <button 
      className={handleSelect(element)}
      key={element}
      onClick={() => handleClick(element)}
      disabled={showResults || (selectedOption !== undefined && selectedOption !== element)}
    >
      {element}
    </button>
  )

  return(
    <>
      <div className='question--container'>
        <h1>
          {question}
        </h1>
        {displayOptions}
      </div>
    </>
  )
}
export default Question

关键逻辑说明

  • 状态提升:把用户的选择从Question组件转移到App组件,让App可以统一获取所有题目的答案并计算得分。
  • 结果展示控制:通过showResults状态控制是否展示对错样式,只有点击判分按钮后才触发高亮。
  • 按钮可用性:只有所有题目都作答后,判分按钮才会启用,避免用户未完成答题就点击判分。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 01:18:18