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

React问答按钮样式问题:如何单独设置按钮颜色而非统一变色

问题分析

你现在的问题是用了一个全局的styleButton状态控制所有按钮样式,导致点击后所有按钮统一变色。要实现单个按钮对应变色,得给每个按钮单独判断样式,而非用统一状态。

修改方案

1. 调整状态定义

删掉全局的styleButton状态,新增记录用户选择和答题状态的变量:

// 移除这行:const [styleButton, setStyleButton] = useState(styles.answerbutton);
const [selectedAnswer, setSelectedAnswer] = useState(null);
const [isAnswered, setIsAnswered] = useState(false);

2. 修改checkAnswer函数

不再设置全局样式,只记录用户选择和标记已答题:

function checkAnswer(answer) {
    const correctAnswer = data[quesno].correct_answer;
    if (answer === correctAnswer) {
        setMessage("Correct Answer!");
        setScore(score + 1);
    } else {
        setMessage("WRONG!!!!");
    }
    setSelectedAnswer(answer);
    setIsAnswered(true);
}

3. 修改nextQuestion函数

切换题目时重置答题相关状态:

function nextQuestion() {
    if (quesno < data.length - 1) {
        setQuesno(quesno + 1);
    }
}

4. 动态渲染按钮样式

遍历渲染按钮时,根据当前答案是否正确、是否被选中分配样式:

{answersArr.map(answer => {
    let btnClass = styles.answerbutton;
    const correctAnswer = data[quesno].correct_answer;
    
    if (isAnswered) {
        if (answer === correctAnswer) {
            btnClass = styles.correctanswer; // 正确答案变绿色
        } else if (answer === selectedAnswer) {
            btnClass = styles.incorrectanswer; // 用户选的错误答案变红色
        }
    }

    return (
        <div className={styles.buttonarrangement} key={answer}>
            <button 
                className={btnClass} 
                onClick={() => checkAnswer(answer)} 
                disabled={isAnswered}
            >
                {answer}
            </button>
        </div>
    );
})}

完整修改后的代码

import { useEffect, useState } from "react";
import styles from '@component/styles/Home.module.css'
import { shuffleArray } from "./Helper";

export default function ShowQuestions() {

    const [data, setData] = useState(null);
    const [quesno, setQuesno] = useState(0);
    const [answersArr, setAnswersArr] = useState([]);
    const [message, setMessage] = useState("");
    const [selectedAnswer, setSelectedAnswer] = useState(null);
    const [isAnswered, setIsAnswered] = useState(false);
    const [score, setScore] = useState(0);
    const [loading, setLoading] = useState(false);

    useEffect(() => {
        async function getData() {
          let res = await fetch(`https://opentdb.com/api.php?amount=10`);
          let body = await res.json();
          setData(body.results);
        }
        
        getData();
      }, []);

    useEffect(() => {
        if (data) {
            setLoading(true);
            const newAnswersArr = [
                data[quesno].correct_answer,
                ...data[quesno].incorrect_answers
            ];
            const shuffledArray = shuffleArray(newAnswersArr);
            setAnswersArr(shuffledArray);
            // 切换题目时自动重置状态
            setIsAnswered(false);
            setSelectedAnswer(null);
            setMessage("");
        }

    }, [data, quesno]);
    
    

    function nextQuestion() {
        if (quesno < data.length - 1) {
            setQuesno(quesno + 1);
        }
    } 
    function checkAnswer(answer) {
        const correctAnswer = data[quesno].correct_answer;
        if (answer === correctAnswer) {
            setMessage("Correct Answer!");
            setScore(score + 1);
        } else {
            setMessage("WRONG!!!!");
        }
        setSelectedAnswer(answer);
        setIsAnswered(true);
    }

    return (
        <section className={styles.box}>
            <div className={styles.centering}>
                <object type="image/svg+xml" data="/loading.svg" hidden={loading} ></object>
            </div>
            {data && (
                    <>
                        <h3 className={styles.centering}>Marks: {score} /10</h3>
                        <p className={styles.category}>{data[quesno].category}</p>
                        <p className={styles.type}>Type: {data[quesno].type}</p>
                        <p className={styles.difficulty}>Difficulty: {data[quesno].difficulty}</p>
                        <p className={styles.question}>{data[quesno].question}</p>

                        {answersArr.map(answer => {
                            let btnClass = styles.answerbutton;
                            const correctAnswer = data[quesno].correct_answer;
                            
                            if (isAnswered) {
                                if (answer === correctAnswer) {
                                    btnClass = styles.correctanswer;
                                } else if (answer === selectedAnswer) {
                                    btnClass = styles.incorrectanswer;
                                }
                            }

                            return (
                                <div className={styles.buttonarrangement} key={answer}>
                                    <button 
                                        className={btnClass} 
                                        onClick={() => checkAnswer(answer)} 
                                        disabled={isAnswered}
                                    >
                                        {answer}
                                    </button>
                                </div>
                            );
                        })}
                    </>
                )}

            {message && (
                <h3 className={styles.centering}>{message}</h3>
            )}
            <div className={styles.nextquestion}>
                <button className={styles.nextbutton}  onClick={nextQuestion} disabled={!isAnswered}>Next question</button>
            </div>
        </section>
    );
}
额外优化点
  • 将able改为isAnswered,语义更清晰;
  • 用扩展运算符简化答案数组构建,替代循环;
  • 切换题目时自动重置答题状态,减少冗余代码;
  • 给「Next question」按钮添加disabled属性,用户未答题时无法点击,优化交互体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:00:36