React中解决map渲染按钮点击时全部变色的问题
解决React中Map渲染按钮的单个颜色修改问题
问题场景
开发颜色序列匹配游戏时,遇到点击按钮后所有按钮颜色同步变化的问题。需求是:玩家猜对序列中的对应颜色按钮时,仅该按钮背景切换为序列中对应位置的颜色,而非全部按钮。
原代码问题分析
- 使用单个
changeColor状态控制所有按钮的背景色,导致修改时所有按钮同步更新。 - 用
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
相关产品推荐
相关产品推荐

