繁体   English   中英

从孙子访问和更改主 React App 中的 state 数组元素

[英]Access and change the state array element in main React App from grandchild

我为这个问题的标题道歉,但我试图在一行中尽可能多地解释这个问题。

我们的学校作业要求我们以某种方式创建(某种)井字游戏。 Instead of creating nine different Box elements from the main App , we were required to create Row class and Box class, so the main App will have three Row class children and each Row class will have three Box children.

现在我遇到的问题是如何在与该确切 Box 组件对应的特定元素处更改主 App state 数组。

我是初学者,如果我没有看到太明显的东西,我会提前道歉。 如果您有任何问题,请尽管提问,我将非常乐意尽我所能解释这一点。 谢谢!

    import React, { Component } from 'react';
    import { render } from 'react-dom';
    
    class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          0 : ['-','-','-'],
          1 : ['-','-','-'],
          2 : ['-','-','-']
        };
        this.handleClick = this.handleClick.bind(this)
      }
      handleClick(){
        // if that particular element is '-' change from '-' to 'X'
        // else if it is 'X' change to 'O'
        // else change to 'X'
      }
      render() {
    
        const rows = []
        for (let i = 0; i < 3; i++) {
          rows.push(<Row key = {i} msg = {this.state[i]} handleClick = {this.handleClick}/>)
        }
    
        return (
          <div>
            <div>
              <h1>Tic Tac Toe</h1>
            </div>
            <div id = 'main'>
              {rows}
            </div>
          </div>
        );
      }
    }
    class Row extends Component{
    
      render() {
        const boxes = []
        for (let i = 0; i < 3; i++) {
          boxes.push(<Box key = {i} msg = {this.props.msg[i]} handleClick = {this.props.handleClick}/>)
        }
        return (
          <div className = 'row'>
            {boxes}
          </div>
        )
      }
    
    }
    
    class Box extends Component{
    
      render() {
        return (
          <div className = 'box' onClick = {this.props.handleClick}>
            <p>{this.props.msg}</p>
          </div>
        )
      }
    
    }
    render(<App />, document.querySelector('#root'));

您已经很好地组织了组件。 您需要在每次点击后处理玩家切换并更新游戏板中的值。

  1. 添加另一个名为player的 state 变量(它可以只是 boolean,因为这是一个两人游戏)
this.state = {
      0: ["-", "-", "-"],
      1: ["-", "-", "-"],
      2: ["-", "-", "-"],
      player: true
    };
  1. 您可以将行和列索引传递给handleClick function,如下所示。
  handleClick(row, col) {
    // set the corresponding value (using row and colum index) in the game borad
    this.setState(
      {
        [row]: this.state[row].map((val, colId) =>
          colId === col ? (this.state.player ? "X" : "O") : val
        )
      },
      () => {
        // switch the player (toggle the player boolean value)
        this.setState({ player: !this.state.player });
      }
    );
  }
  1. Box组件的点击处理程序中传递rowcol ID。
       <Box
          ...
          ...
          handleClick={() => {
            this.props.handleClick(this.props.row, i);
          }}
        />

代码沙箱

注意:当您进一步开发以避免通过单击更改同一个框时,您可以保留 object 来存储更多信息,例如{ value: "-", used: false }而不是"-"作为值。

根据@Amila Senadheera 的回答,您还可以在 handleClick function 中添加一个检查,以确保玩家无法覆盖其他玩家的移动。 类似于以下内容:

handleClick(row, col) {
    // set the corresponding value (using row and colum index) in the game board
    if(this.state[row][col] !== '-') {
      return // Don't allow the player to overwrite an already-marked square.
    }
    this.setState(
      {
        [row]: this.state[row].map((val, colId) =>
          colId === col ? (this.state.player ? "X" : "O") : val
        )
      },
      () => {
        // switch the player (toggle the player boolean value)
        this.setState({ player: !this.state.player });
      }
    );
  }

如果你想为胜利添加检查,这里有一些有用的讨论: https://codereview.stackexchange.com/questions/24764/tic-tac-toe-victory-check

您可以为 handleClick 定义参数,例如

type T = 1 | 2 | 3;
function handleClick(row: T, col: T) {
  const newRow = [ ...this.state[row] ];
  this.sign = this.sign === "O" ? "X" : "O";
  newRow[col] = this.sign;
  this.setState({...this.state, [row]: newRow});
}

然后你需要 Box 的新道具:

for (let i = 0; i < 3; i++) {
  boxes.push(
    <Box 
      row={props.row}
      col={i}
      key={i} 
      msg={this.props.msg[i]} 
      handleClick={this.props.handleClick}/>
  )
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM