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
相关产品推荐
相关产品推荐

