React颜色游戏开发问题:main_color初始为undefined且取值滞后求助
问题根源
setState是异步批量更新的,你在newgame方法中连续调用两次setState后立即读取state值,拿到的还是更新前的旧值,所以会出现main_color滞后、初始为undefined的问题。- 你在
componentDidMount中绑定盒子点击事件时,捕获的main_color是初始化的空字符串,后续state更新后这个绑定的回调里的main_color不会同步更新,导致颜色判断逻辑永远失效。 - 大量直接操作DOM的写法不符合React的声明式设计,后续状态变更很容易出现数据和视图不同步的问题。
修复后代码
import React from "react"; import "../css/App.css" import { RandomGenerator } from "../logics/Logics" class Main extends React.Component { state = { color: [], main_color: "", mode: "easy" // 用来控制难度,不需要操作DOM切换显示 } // 统一的游戏初始化逻辑,不需要重复写easy、hard里的重复代码 initGame = (boxCount) => { const colors = RandomGenerator(boxCount); const pickedColor = colors[Math.floor(Math.random() * boxCount)]; // 单次setState更新所有状态,不需要拆分调用 this.setState({ color: colors, main_color: pickedColor, mode: boxCount === 3 ? "easy" : "hard" }) } // 点击盒子的判断逻辑,不用原生绑定事件,直接在JSX里绑定 handleBoxClick = (color) => { if (color === this.state.main_color) { console.log("winner"); } else { console.log("loose"); } } componentDidMount() { // 页面加载默认初始化简单难度 this.initGame(3); } render() { const {color, main_color, mode} = this.state; return ( <div> <div className="upper-sec"> <p className="display-6 text-center pt-3"> 超棒的 <br /> <span className="rgb ">{main_color.toUpperCase()}</span> <br />猜色游戏 </p> </div> <div className="the-line d-flex justify-content-between"> <button className="btn btn-outline-secondary button" style={{ marginLeft: "150px" }} onClick={() => this.initGame(mode === "easy" ? 3 : 6)} > 新游戏 </button> <div> <button className="btn btn-outline-success button me-5" onClick={() => this.initGame(3)} > 简单 </button> <button className="btn btn-outline-danger button " style={{ marginRight: "150px" }} onClick={() => this.initGame(6)} > 困难 </button> </div> </div> <div className="box-main"> <div className="easy mt-2"> {color.slice(0,3).map((item, index) => ( <div key={index} className="boxes" style={{backgroundColor: item}} onClick={() => this.handleBoxClick(item)} ></div> ))} </div> <div className="hard" style={{ display: mode === "hard" ? "block" : "none" }}> {color.slice(3,6).map((item, index) => ( <div key={index} className="boxes" style={{backgroundColor: item}} onClick={() => this.handleBoxClick(item)} ></div> ))} </div> </div> </div> ) } } export default Main;
核心修改说明
- 把重复的游戏初始化逻辑抽成统一的
initGame方法,单次调用setState更新所有状态,避免异步取值问题 - 移除所有原生DOM操作,用React的状态控制视图渲染、事件绑定,保证数据和视图永远同步
- 盒子点击事件直接绑定在JSX元素上,每次触发都会拿到最新的
main_color值,不会出现判断失效的问题
内容的提问来源于stack exchange,提问作者Hayder Ali
相关产品推荐
相关产品推荐

