简体   繁体   English

在哪里处理父子事件React

[英]Where to handle parent-child event React

I'm getting start with React basic concepts, and I'm not sure how to proceed... 我正在开始使用React基本概念,但不确定如何继续...

I'm trying to build a simple Minesweeper game, my structure is a MinesweeperField wrapper, with height, width and minesNumber as props, and a MinesweeperTile, with value (is it a mine/number of close mines) and explored as props. 我正在尝试构建一个简单的Minesweeper游戏,我的结构是一个MinesweeperField包装器,其中高度,宽度和minesNumber作为道具,以及一个MinesweeperTile,其值(它是一个地雷/近距离地雷的数量)并作为道具进行了探索。

My problem is, I'm not sure how to handle clicking on the tiles. 我的问题是,我不确定如何处理点击图块。 The MinesweeperField component must be notified when a tile is explored to handle the new game state (ex: in case of game over or win), and it must also be able to trigger explore in other tiles (for example, if you click on a tile with 0 close mines, all of the adjacent tiles must be explored automatically). 当探索图块以处理新的游戏状态时(例如,如果游戏结束或获胜),必须通知MinesweeperField组件,并且它还必须能够触发其他图块中的探索(例如,如果单击具有0个近地雷的图块,则必须自动探索所有相邻的图块)。

From what I understood there are two approaches: 据我了解,有两种方法:

  • Handle click on the Tile, Tile notifies Field, Field triggers explore also on adjacent Tiles - notifying Field from Tile is easy, but calling Tile from Field would require to use refs, plus a different click handler function is instantiated for each Tile 处理在Tile上的单击,Tile通知Field,Field触发器也在相邻的Tile上进行探索-从Tile通知Field很容易,但是从Field调用Tile则需要使用引用,并且为每个Tile实例化一个不同的单击处理函数
  • Handle click on Field, Field updates the prop that in render is used to assign the isExplored prop to the Tile - since I render the Tile based on an array variable in the Field's state, I have to use setState to trigger a redraw of child Tiles components. 处理Field上的单击,Field更新在render中用于将isExplored prop分配给Tile的道具-由于我基于Field状态下的数组变量渲染Tile,因此我必须使用setState触发子Tile的重绘组件。

this is a simplified sample of the render function, in the "Handle Click on Field" version: 这是“ Handle Click on Field”版本中的渲染功能的简化示例:

return (
            <div className="minesweeper-wrapper">
                <div className="minesweeper-field" style={this.getDimensions()}>
                    {this.state.proximityMap.map(function(verticalRow, vIndex){
                        return verticalRow.map(function(tileValue, hIndex){
                            return <MinesweeperTile value={tileValue} hIndex={hIndex} vIndex={vIndex} onClick={this.exploreTile.bind(this, vIndex, hIndex, tileValue)} isExplored={this.state.explorationMap[vIndex][hIndex]} />
                        });    
                    })}
                </div>
            </div>
        );

and here's the exploreTile function: 这是explorerTile函数:

exploreTile(vIndex, hIndex, tileValue) {
        this.unveilTile(vIndex, hIndex);
        if (tileValue < 0) {
            this.gameOver();
        } else {
            if (tileValue === 0) {
                this.propagateTileExplore(vIndex, hIndex);
            }
        }
    }

this.state.proximityMap contains values indicating how many mines are close to this tile/is this tile a mine. this.state.proximityMap包含一些值,这些值指示有多少地雷靠近该图块/该图块是否是地雷。 this.state.explorationMap contains bools indicating which tiles have been explored. this.state.explorationMap包含指示已浏览哪些图块的this.state.explorationMap值。

My problem with this approach is that, from what I understood, if I want to redraw a single tile, I have to call setState on Field and update this.state.explorationMap array, which will redraw every tile! 根据我的理解,这种方法的问题在于,如果我想重绘单个图块,则必须在Field上调用setState并更新this.state.explorationMap数组,该数组将重绘每个图块!

Any ideas as to how I could limit the redraw to a single Tile? 关于如何将重绘限制为单个图块的任何想法? Should I keep exploring the "handle click on Field" way or go back to "handle click on Tile"? 我应该继续探索“点击字段处理”方式还是回到“点击瓷砖处理”?

I started with "handle click on Tile" but I stopped when I got to the "explore adjacent tiles" problem. 我从“单击瓷砖上的手柄”开始,但是在遇到“探索相邻瓷砖”问题时我停了下来。

Also please no jQuery/js tricks or hacks to solve this in an unconventional way, it's not about finding a way to do this, but finding the most appropriate. 另外,请不要使用jQuery / js技巧或骇客以非常规的方式解决此问题,这不是找到一种方法来实现,而是找到最合适的方法。 It won't probably make a noticeable difference in the context of a Minesweeper game, but as I said, it's for training purposes :) 在扫雷游戏的背景下,它可能不会产生明显的变化,但是正如我所说的,这是出于训练目的:)

The most appropriate way would be to let the parent handle the changes. 最合适的方法是让父母处理更改。 The children just need to know whom to call when they are clicked and how they should look like. 孩子们只需要知道被点击时给谁打电话以及他们的样子。 I did the same thing in my Game of Life clone using React. 我使用React在生命游戏克隆中做了同样的事情。

CodePen Link CodePen链接

changeTile(row, col) {
    if (!this.state.isPlaying) {
      const newTile = this.state.board[row][col] === 1 ? 0 : 1;
      const newRow = [...this.state.board[row]];
      newRow.splice(col, 1, newTile);
      const newBoard = [...this.state.board];
      newBoard.splice(row, 1, newRow);
      this.setState({
        board: newBoard
      });
    }
  }

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

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