React函数组件中实现.map()渲染的单个答题选项点击后样式独立切换的方案
解决React Quiz选项点击仅改变单个组件样式的问题
嘿,我看你现在的问题是点击某个答题选项时,所有选项的样式都跟着变了对吧?这是因为你用了一个全局的correct布尔状态——只要这个状态变成true,所有通过map渲染的AnswerOption组件都会触发correct类的样式,自然做不到只改变点击的那个选项。咱们调整一下状态管理的逻辑就能搞定:
核心思路
把单一的布尔状态改成记录用户选中的具体选项,然后让每个AnswerOption组件自己判断:我是不是被选中的那个?我是不是正确答案?以此来决定应用什么样式。
修改后的完整代码
主组件部分
import { useState, Fragment } from 'react'; import Question from './Question'; import AnswerOption from './AnswerOption'; const Quiz = () => { // 替换原来的correct状态,用selectedAnswer存储用户点击的选项内容 const [selectedAnswer, setSelectedAnswer] = useState(null); const DUMMY_QUESTIONS = [ { id: 1, question: 'What is the Big O of merge sort?', options: [ { number: 1, answer: 'O(1)'}, { number: 2, answer: 'O(log n)' }, { number: 3, answer: 'O(n)' }, { number: 4, answer: 'O(n log n)' } ], answer: 'O(n log n)' } ]; // 处理选项点击,存储用户选中的选项 const handleOptionClick = (selected) => { setSelectedAnswer(selected); }; return ( <Fragment> <div> <Question question={DUMMY_QUESTIONS[0].question} /> </div> <div> {DUMMY_QUESTIONS[0].options.map(option => <AnswerOption key={option.number} id={option.number} option={option.answer} // 告诉组件:我是不是被选中的?我是不是正确答案? isSelected={selectedAnswer === option.answer} isCorrect={option.answer === DUMMY_QUESTIONS[0].answer} click={() => handleOptionClick(option.answer)} /> )} </div> </Fragment> ); }; export default Quiz;
AnswerOption组件部分
const AnswerOption = props => { // 根据选中状态和是否正确拼接类名 let optionClass = 'answer-option'; if (props.isSelected) { optionClass += props.isCorrect ? ' answer-option--correct' : ' answer-option--incorrect'; } return ( <div className={optionClass} onClick={() => props.click(props.option)}> <p>{props.option}</p> </div> ); }; export default AnswerOption;
为什么这样有效?
- 状态精准控制:
selectedAnswer只会存储用户点击的那一个选项内容,不会影响其他选项 - 组件独立判断:每个
AnswerOption只关心自己是否是被选中的那个,以及自己是否是正确答案,完全独立于其他选项的状态 - 样式逻辑清晰:通过拼接类名的方式,只有被选中的选项才会根据对错应用绿色/红色背景
可选优化(按需添加)
如果想让用户选中后不能再点击其他选项,可以给AnswerOption的点击事件加个判断:
// 在AnswerOption组件里修改onClick onClick={() => !props.isSelected && props.click(props.option)}
内容的提问来源于stack exchange,提问作者eric L
相关产品推荐
相关产品推荐

