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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 02:51:00