簡體   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