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

React Quiz App开发技术问询:如何实现仅被点击的按钮变色

解决React Quiz App中点击按钮全部变色的问题

嘿,很高兴看到你第一次React项目就做Quiz App!咱们来解决这个点击按钮全部变色的问题——根源其实很简单:你现在用了一个全局的color状态,所有的Quiz组件都共享这个状态,所以不管点哪个按钮,所有按钮都会跟着变颜色。

下面给你两种可行的解决方案,你可以根据自己的需求选一种:


方案一:让每个Quiz组件独立管理选中状态

这种方法最简单直接,每个Quiz组件自己维护自身的选中选项ID,各个题目之间互不干扰。

修改Quiz.js

import blob1 from './blob1.png'
import blob2 from './blob2.png'
import { useState } from 'react' // 引入useState

export default function Quiz(props) {
  // 每个Quiz组件单独存储选中的选项ID,初始为null表示未选中
  const [selectedId, setSelectedId] = useState(null)

  // 根据按钮ID是否匹配选中ID,动态生成样式
  const getButtonStyle = (id) => ({
    backgroundColor: selectedId === id ? '#D6DBF5' : '#F5F7FB',
    border: selectedId === id ? '1px solid #293264' : '1px solid black'
  })

  return (
    <div className='quiz-body'>
      <img src={blob1} className="blob1"/>
      <img src={blob2} className="blob2"/>
      <h2 className='h2-quiz'>{props.question}</h2>
      {/* 遍历选项数组渲染按钮,替代原来写死的四个按钮 */}
      {props.answerOptions.map(option => (
        <button 
          key={option.id} // 必须加key,React列表渲染的要求
          className='btn-ans' 
          onClick={() => setSelectedId(option.id)} 
          style={getButtonStyle(option.id)}
        >
          {option.answerText}
        </button>
      ))}
      <br/>
      <br/>
      <hr/>
    </div>
  )
}

修改App.js中的渲染逻辑

把原来单独传递answer1-4的方式改成直接传递整个answerOptions数组:

const quizQ = qanda.map(ques => 
  <Quiz 
    key={ques.question} // 给每个Quiz组件加唯一key
    question={ques.question} 
    answerOptions={ques.answerOptions} // 直接传递选项数组
  />
)

同时你可以删掉App.js里的color状态和switchColor函数了,因为每个Quiz现在自己管理选中状态。


方案二:在父组件(App)统一管理所有选中状态

如果之后需要实现提交答案、计算得分的功能,这种方法更合适——所有选中状态都存在父组件中,方便后续统一处理。

修改App.js

import Main from './Main'
import Quiz from './Quiz'
import { useState } from 'react'
export default function App() {
  const [switch1, setSwitch1] = useState(false)
  // 用对象存储每个题目对应的选中选项ID,键用题目内容作为唯一标识
  const [selectedAnswers, setSelectedAnswers] = useState({})

  const qanda = [
    // 你的题目数据保持不变
  ]

  // 更新选中答案的函数:接收题目标识和选项ID
  const handleSelectAnswer = (question, optionId) => {
    setSelectedAnswers(prev => ({
      ...prev,
      [question]: optionId // 更新对应题目的选中ID
    }))
  }

  const quizQ = qanda.map(ques => 
    <Quiz 
      key={ques.question}
      question={ques.question} 
      answerOptions={ques.answerOptions}
      selectedId={selectedAnswers[ques.question]} // 把当前题目的选中ID传给Quiz
      onSelect={(optionId) => handleSelectAnswer(ques.question, optionId)} // 传递选择回调
    />
  )

  function switchIt() {
    setSwitch1(prevValue => !prevValue)
  }

  return (
    <div className="body">
      {switch1 ? quizQ : <Main onclick={switchIt}/> }
    </div>
  )
}

修改Quiz.js

import blob1 from './blob1.png'
import blob2 from './blob2.png'

export default function Quiz(props) {
  const getButtonStyle = (id) => ({
    backgroundColor: props.selectedId === id ? '#D6DBF5' : '#F5F7FB',
    border: props.selectedId === id ? '1px solid #293264' : '1px solid black'
  })

  return (
    <div className='quiz-body'>
      <img src={blob1} className="blob1"/>
      <img src={blob2} className="blob2"/>
      <h2 className='h2-quiz'>{props.question}</h2>
      {props.answerOptions.map(option => (
        <button 
          key={option.id}
          className='btn-ans' 
          onClick={() => props.onSelect(option.id)} 
          style={getButtonStyle(option.id)}
        >
          {option.answerText}
        </button>
      ))}
      <br/>
      <br/>
      <hr/>
    </div>
  )
}

额外小建议

  • 列表渲染时一定要加key属性,这是React的最佳实践,能避免不必要的渲染错误。
  • 不要单独传递answer1、answer2这类props,直接传递整个选项数组然后遍历渲染,代码会更灵活,以后选项数量变化也不用修改组件结构。

加油,你的第一个React项目已经做得很棒了,继续坚持下去!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:43:11