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

React开发Lights Out游戏时子组件向父组件更新数组数据混乱如何解决

问题根源
  • 子组件点击逻辑无状态校验:clickHandler触发时,未判断当前灯的亮灭状态,无论操作是点亮还是熄灭,都直接调用父组件方法追加序号,导致数组仅持续新增内容,和实际亮灯情况不匹配。
  • 父组件同步方法逻辑缺失:现有showNum方法仅支持向数组追加内容,没有实现灯熄灭时移除对应序号的逻辑。
  • 初始化逻辑存在副作用风险:子组件rand方法内部直接调用父组件传值方法,React 18 严格模式下组件会二次挂载初始化,会导致初始亮灯序号重复插入数组。
修复方案

调整父子组件逻辑,让父组件的lightNums数组始终和当前亮灯序号一一对应,亮灯新增、灭灯移除:

父组件修改

将原本仅支持追加的showNum方法调整为支持新增/移除的切换方法,自动判断序号是否存在于数组中做对应操作:

import "./App.css";
import Square from "./Square";
import React, { Component } from "react";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      lightNums: [],
    };
  }
  // 支持亮灯新增、灭灯移除的同步方法
  toggleLightNum(num) {
    this.setState((prevState) => {
      const { lightNums } = prevState;
      return lightNums.includes(num) 
        ? { lightNums: lightNums.filter(item => item !== num) }
        : { lightNums: [...lightNums, num] };
    });
  }

  arr = Array.from({ length: 25 }).map((e, idx) => {
    return <Square num={idx} key={idx} toggleLightNum={this.toggleLightNum.bind(this)} />;
  });

  render() {
    return <div className="App">{this.arr}</div>;
  }
}

export default App;

子组件修改

移除rand方法内的父组件调用,把初始化同步逻辑放到构造函数内,避免重复执行;点击时无需额外判断,直接调用父组件切换方法即可:

import React, { Component } from "react";
import "./Square.css";

class Square extends Component {
  constructor(props) {
    super(props);
    this.clickHandler = this.clickHandler.bind(this);
    // 初始化随机亮灯状态
    const initClicked = this.getRandomInitState();
    this.state = {
      clicked: initClicked,
    };
    // 初始状态为亮灯时,同步到父组件
    if (initClicked) {
      this.props.toggleLightNum(this.props.num);
    }
  }

  clickHandler() {
    this.setState((prevState) => {
      const newState = !prevState.clicked;
      // 状态更新后同步到父组件
      this.props.toggleLightNum(this.props.num);
      return { clicked: newState };
    });
  }

  getRandomInitState() {
    return Math.floor(Math.random() * 2) === 1;
  }

  classN = () => `square ${this.state.clicked ? "clicked" : ""}`;

  render() {
    return (
      <div className={this.classN()} onClick={this.clickHandler}>
        {this.props.num}
      </div>
    );
  }
}

export default Square;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 01:36:04