React答题网站按钮ID重复问题:如何为每个按钮分配唯一ID
为React答题网站的每个选项按钮分配唯一ID的解决方案
你的问题核心是:给每道题传了同一个ID,导致该题下所有按钮点击后返回的ID都一样,根本没给单个按钮分配独立标识。下面是具体的修复方案:
步骤1:重构选项数据,给每个选项生成唯一ID
首先在App组件里,把每道题的正确答案和错误答案合并成一个数组,同时用nanoid给每个选项生成唯一ID,还能顺便打乱选项顺序(符合答题网站的常规需求)。
步骤2:修改QuestionPage组件,渲染带唯一ID的选项按钮
让QuestionPage接收处理后的选项列表,每个按钮点击时传递对应选项的ID和内容,而非整道题的ID。
步骤3:更新状态管理,跟踪用户选择
在App组件里维护状态,记录用户每道题选择的选项ID,方便后续验证答案。
修改后的App组件代码
import QuestionPage from "./components/Question_page"; import React from "react"; import { nanoid } from 'nanoid' import { BrowserRouter as Router, Route, Routes } from "react-router-dom" import JsonData from "./JsonData"; export default function App() { // 维护用户选择:key是题目索引,value是选中的选项ID const [userAnswers, setUserAnswers] = React.useState({}); // 处理题目数据:合并选项+生成唯一ID+打乱顺序 const processedQuestions = JsonData[0].results.map((question, questionIndex) => { // 合并正确和错误选项,给每个选项加唯一ID和是否正确的标记 const allOptions = [ ...question.incorrect_answers, question.correct_answer ].map(option => ({ id: nanoid(), text: option, isCorrect: option === question.correct_answer })); // 打乱选项顺序(可选,答题网站常用) const shuffledOptions = allOptions.sort(() => Math.random() - 0.5); return { ...question, options: shuffledOptions, questionIndex }; }); // 处理选项点击:记录用户选择的题目索引和选项ID function handleOptionSelect(questionIndex, optionId) { setUserAnswers(prev => ({ ...prev, [questionIndex]: optionId })); console.log(`题目${questionIndex+1},选中选项ID:${optionId}`); } // 验证答案逻辑 function checkAnswers() { let score = 0; processedQuestions.forEach((question, index) => { const selectedOption = question.options.find(opt => opt.id === userAnswers[index]); if (selectedOption?.isCorrect) { score++; } }); alert(`你的得分是:${score}/${processedQuestions.length}`); } return ( <Router> <NavBar/> <Routes> <Route path="/" element={<Start/>}/> <Route path="/question" element={ <div> {processedQuestions.map((question) => ( <QuestionPage key={question.questionIndex} question={question.question} options={question.options} selectedOptionId={userAnswers[question.questionIndex]} onOptionSelect={(optionId) => handleOptionSelect(question.questionIndex, optionId)} /> ))} <div className="check-answer-container"> <button className="check-answer" onClick={checkAnswers}>Check answer</button> </div> <hr/> </div> }/> </Routes> </Router> ); }
修改后的QuestionPage组件代码
import React from "react"; export default function Question_page(props) { // 根据是否选中设置按钮样式 const getButtonStyle = (optionId) => ({ backgroundColor: props.selectedOptionId === optionId ? "#59E391" : "grey", margin: "5px", padding: "8px 16px", border: "none", borderRadius: "4px", cursor: "pointer" }); return ( <div className="main-question-container"> <div className="question"> <h3>{props.question}</h3> </div> <div className="question-button"> {props.options.map(option => ( <button key={option.id} style={getButtonStyle(option.id)} onClick={() => props.onOptionSelect(option.id)} > {option.text} </button> ))} </div> </div> ); }
关键改动说明
- 每个选项都有了独立的
nanoid生成ID,点击按钮时传递的是选项自身的ID,不再是整道题的ID - 合并并打乱选项顺序,更贴近真实答题场景
- 用
userAnswers状态跟踪用户每道题的选择,便于后续验证答案和更新按钮样式 - QuestionPage组件根据选中状态动态切换按钮背景色,无需依赖原有的
isHeld属性
内容的提问来源于stack exchange,提问作者Tombrown Anuma
相关产品推荐
相关产品推荐

