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

React答题组件需求:点击题目选项后仅禁用该题其余选项

React答题组件问题修复

问题说明

现有React答题组件存在以下问题:点击任意选项后,所有题目里的选项都会被禁用。需要实现两个需求:

  1. 点击某道题的选项时,只禁用这道题的其他选项
  2. 所有题目都作答完成后,显示结果按钮

原组件代码

setIsStarted(true)
        setCurrentScore(0)
        setResultCard(false)
        setCurrentQuestion(0)
    }   

    const checkOption = (isCorrect) =>{
        setDisability(true)
        if(isCorrect){
            setCurrentScore(currentScore+1);
        }
        setCurrentQuestion(currentQuestion+1);

        if(currentQuestion==questions.length-1){
            setShowResult(true);
        }

    }

    function showResultButton(showResult){
        if (showResult) {
            return <button className='show-result' onClick={showResultCard}>Show results</button>
        }
    }

    const showResultCard = () =>{
        setShowResult(false)
        setResultCard(true);
        setIsStarted(false)
    }

    function displayResultCard(resultCard){
        
        if(resultCard){
            return <div className='score-card'>You have answerd {currentScore}/5 correctly</div>
        }
    }

    const updateDisability = () =>{
        setDisability(false)
    }

    function DisplayQuesion(){
        const quesList = questions.map((element) => {
            return(
                <div className='question-card'>
                    <h2>{element.text}</h2>
                    <ul>
                        {element.options.map((option) => {
                            return <button key={option.id} onClick={() => checkOption(option.isCorrect)} disabled={updateDisability}>{option.text}</button>
                        })}
                    </ul>
                </div>
            )
        })

        return (<div>{quesList}</div>)
    }

修改后的完整代码

import { useState } from 'react';

function QuizComponent() {
    const [isStarted, setIsStarted] = useState(false);
    const [currentScore, setCurrentScore] = useState(0);
    const [resultCard, setResultCard] = useState(false);
    const [showResult, setShowResult] = useState(false);
    // 新增状态:记录每道题选中的选项ID,key为题目索引
    const [selectedOptions, setSelectedOptions] = useState({});

    // 示例题目结构,可根据实际需求替换
    const questions = [
        {
            text: "问题1:React的核心特性是什么?",
            options: [
                { id: 1, text: "双向数据绑定", isCorrect: false },
                { id: 2, text: "虚拟DOM", isCorrect: true },
                { id: 3, text: "后端渲染", isCorrect: false }
            ]
        },
        {
            text: "问题2:useState返回的是哪种类型的值?",
            options: [
                { id: 4, text: "一个值", isCorrect: false },
                { id: 5, text: "一个数组", isCorrect: true },
                { id: 6, text: "一个对象", isCorrect: false }
            ]
        }
    ];

    const startQuiz = () => {
        setIsStarted(true);
        setCurrentScore(0);
        setResultCard(false);
        setShowResult(false);
        setSelectedOptions({}); // 清空上一轮的选中记录
    }   

    const checkOption = (isCorrect, questionIndex, optionId) =>{
        // 记录当前题目的选中选项
        setSelectedOptions(prev => ({...prev, [questionIndex]: optionId}));
        // 函数式更新得分,避免闭包导致的计算错误
        if(isCorrect){
            setCurrentScore(prev => prev + 1);
        }
        // 检查是否所有题目都已作答
        if(Object.keys(selectedOptions).length + 1 === questions.length){
            setShowResult(true);
        }
    }

    const showResultButton = () =>{
        if (showResult) {
            return <button className='show-result' onClick={showResultCard}>查看结果</button>
        }
    }

    const showResultCard = () =>{
        setShowResult(false);
        setResultCard(true);
        setIsStarted(false);
    }

    const displayResultCard = () =>{
        if(resultCard){
            return <div className='score-card'>你答对了 {currentScore}/{questions.length} 道题</div>;
        }
    }

    const DisplayQuestion = () =>{
        const quesList = questions.map((element, questionIndex) => {
            const selectedOptionId = selectedOptions[questionIndex];
            return(
                <div className='question-card' key={questionIndex}>
                    <h2>{element.text}</h2>
                    <ul>
                        {element.options.map((option) => {
                            // 禁用逻辑:当前题目已有选中选项,且当前选项不是用户选的那个
                            const isDisabled = selectedOptionId && selectedOptionId !== option.id;
                            return (
                                <button 
                                    key={option.id} 
                                    onClick={() => checkOption(option.isCorrect, questionIndex, option.id)} 
                                    disabled={isDisabled}
                                >
                                    {option.text}
                                </button>
                            );
                        })}
                    </ul>
                </div>
            )
        })

        return (<div>{quesList}</div>)
    }

    return (
        <div className='quiz-container'>
            {!isStarted && !resultCard && <button onClick={startQuiz}>开始答题</button>}
            {isStarted && DisplayQuestion()}
            {showResultButton()}
            {displayResultCard()}
        </div>
    );
}

export default QuizComponent;

关键修改说明

  1. 新增状态追踪选中选项:添加selectedOptions状态,用对象存储每道题用户选中的选项ID,精准控制单题的禁用范围。
  2. 调整选项禁用逻辑:每个选项的disabled属性不再依赖全局开关,而是判断当前题目是否已有选中选项,且当前选项不是用户选择的那个——实现点击某题选项后,仅禁用该题其他选项的需求。
  3. 修复得分计算的闭包问题:将setCurrentScore(currentScore+1)改为函数式更新setCurrentScore(prev => prev + 1),避免因闭包导致的得分统计错误。
  4. 完善结果触发条件:原来用currentQuestion判断是否完成答题的逻辑不准确,现在改为检查selectedOptions的键数量是否等于题目总数,确保所有题目都作答后才显示结果按钮。
  5. 优化中文显示:将按钮文字和结果提示改为中文,贴合国内使用场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 19:56:13