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

React中解决map渲染按钮点击时全部变色的问题

解决React中Map渲染按钮的单个颜色修改问题

问题场景

开发颜色序列匹配游戏时,遇到点击按钮后所有按钮颜色同步变化的问题。需求是:玩家猜对序列中的对应颜色按钮时,仅该按钮背景切换为序列中对应位置的颜色,而非全部按钮。

原代码问题分析

  1. 使用单个changeColor状态控制所有按钮的背景色,导致修改时所有按钮同步更新。
  2. 用let ctr直接管理计数,组件每次渲染都会重置ctr为0,导致逻辑混乱。

解决方案及修改代码

步骤1:重构状态管理

  • 用buttonColors对象状态替代单个changeColor,记录每个按钮的当前颜色。
  • 用useState维护计数器ctr,避免渲染重置。

步骤2:修改初始化逻辑

洗牌按钮时,同步初始化每个按钮的默认颜色。

步骤3:修改颜色更新逻辑

猜对时仅更新对应按钮的颜色,而非全局状态。

修改后的完整代码

//declaring the colors
const colorSequence = [
  { "color":  "#3db44b" },
  { "color":  "#bfef45" },
  { "color":  "#42d3f4" },
  { "color":  "#4263d8" },
  { "color":  "#f68232" },
  { "color":  "#fee118" },
  { "color":  "#e6194a" },
  { "color":  "#f032e6" },
  { "color":  "#921eb3" }
]

function App() {
  const [colors, setColors] = useState<{ color: string }[]>([])
  const [buttons, setButtons] = useState<{ color: string }[]>([])
  // 用对象记录每个按钮的当前颜色,键为按钮的color值
  const [buttonColors, setButtonColors] = useState<Record<string, string>>({})
  // 用useState维护计数器,避免渲染重置
  const [ctr, setCtr] = useState(0)
  
  //shuffle the color sequence
  const shuffleColors = () => {
    const shuffledColors = [...colorSequence]
      .sort(() => Math.random() - 0.5)
      .map((color) => ({ ...color }))

    setColors(shuffledColors)
    shuffleButtons()
  }
  //shuffle the buttons
  const shuffleButtons = () => {
    const shuffledButtons = [...colorSequence]
      .sort(() => Math.random() - 0.5)
      .map((color) => ({ ...color }))

    setButtons(shuffledButtons)
    // 初始化每个按钮的默认颜色
    const initButtonColors = shuffledButtons.reduce((acc, btn) => {
      acc[btn.color] = '#451252'; // 设置初始默认色
      return acc;
    }, {} as Record<string, string>)
    setButtonColors(initButtonColors)
  }
  //check Sequence
  const checkSequence = (event: React.MouseEvent, colorCode:string) => {
    console.log(colorCode, colors[ctr]?.color, ctr)
    // 确保colors数组已初始化
    if (!colors[ctr]) return
    
    if(colorCode === colors[ctr].color){
      // 仅更新当前猜对的按钮颜色为序列对应位置的颜色
      setButtonColors(prev => ({
        ...prev,
        [colorCode]: colors[ctr].color
      }))
      // 更新计数器
      setCtr(prev => prev + 1)
    } else {
      // 猜错重置计数器
      setCtr(0)
      // 可选:重置所有按钮颜色
      // shuffleButtons()
    }

    if(ctr + 1 === colors.length){
      alert('Congrats! Good Job!')
      setCtr(0)
      shuffleButtons()
      shuffleColors()
    }
  }
  
  return (
    <div className="App">
      <Button variant='contained' onClick={shuffleColors}>New Game</Button>

      <div className = "color-seq">
        {colors.map(color => (
          <div className="color" key={color.color}>
              <div className="square" style={{backgroundColor: color.color}}/>
          </div>
        ))}
      </div>

      <div className="color-button">
        {buttons.map(button => (
          <div className="button" key={button.color}>
              <Button 
                variant='contained'
                style={{backgroundColor: buttonColors[button.color] || '#451252'}}    
                onClick={(e) => {checkSequence( e, button.color )}}>{button.color}
              </Button>
          </div>
        ))}
      </div>
    </div>
  );
}

export default App;

关键修改说明

  • buttonColors对象通过按钮的color值作为键,精准控制每个按钮的背景色。
  • 更新颜色时使用函数式更新setButtonColors(prev => ({...prev, [colorCode]: ...})),确保状态更新基于最新值。
  • 用useState管理ctr,避免组件渲染时计数器被重置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 10:35:17