React中自动触发特定组件的OnClick事件

Automatically trigger an OnClick event of a specific component in React

我是 React 的初学者并且 Javascript 我正在尝试从头开始在 React 中创建扫雷器。我 运行 遇到了一个问题,我想复制扫雷器的功能,如果您单击周围有零地雷的图块,周围的图块将自动显示出来。但是,我无法弄清楚如何做到这一点。我的直觉是通过 id 获取周围的图块,并以某种方式手动触发 OnClick 事件,但据我所知,我的 Tile 组件不知道其他 Tile 组件,因此无法访问它们。而且我看不出如何从我的 Board 组件中做到这一点。任何建议将不胜感激!

板组件:

class Board extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            height: 8,
            width: 8,
            num_mines: 10
        }
        game_logic.initalizeGame(8,8,10);
        game_logic.createGame();
    }

    render() {
        var all_tiles = [];
        for (var i = 0; i < this.state.height; i++) {
            var row_tiles = [];
            for (var j = 0; j < this.state.width; j++) {
                row_tiles.push(<Tile key={'Tile ' + (i*this.state.height + j)} value={game_logic.tile_values[i][j]} />)
            }
            all_tiles[i] = row_tiles;
        }

        return (
            <div>
                {all_tiles.map((value, index) => {
                    return <div key={'Row ' + index}>{value}</div>
                })} 
            </div>
        )
    }
}

export default Board;

磁贴组件:

class Tile extends React.Component {

    
    constructor(props) {
        super(props);
        this.state = {
            imgSrc: null,
            imgAlt: '',
            value: '',
        };
    }

    tileClick = (e) => {
        //left click: unveil tile
        if (e.type === "click" && this.state.imgAlt === '') {
            if (this.props.value < 0) {
                this.setState({value: '', imgSrc: mine, imgAlt: "mine"});
            }
            else {
                this.setState({value: this.props.value})
                if (this.props.value === 0) {
                    //automatically left click all 8 surrounding tiles
                }
            }
        }
        //right click: mark or unmark tile
        else if (e.type === "contextmenu") {
            e.preventDefault();
            if (this.state.value === '' && this.state.imgAlt !== "mine") {
                if (this.state.imgAlt !== '') {
                    this.setState({imgSrc: null, imgAlt: ''});
                }
                else {
                    this.setState({imgSrc: flag, imgAlt: "flag"});
                }
            }
        }
    }
    
    render() {
        return (
            <button 
                className="tile" 
                onClick={this.tileClick} onContextMenu={this.tileClick}>
                    <img src={this.state.imgSrc} alt={this.state.imgAlt} />
                    {this.state.value}
            </button>
        );
    }
}

export default Tile;

您好,您必须更新线路 {this.state.value} 与下面 {this.state.value}

您需要 child 组件才能查看 parent 的 game_logic.tile_values 并对其进行操作。虽然可以从 parent 向下传递值并尝试在那里对它们做一些事情,但将点击处理程序放在 parent 所以一切都可以从那里轻松访问。

您还需要改变处理状态的方式。让每个单独的组件都有自己的状态将使 cross-component 通信变得非常困难,但这是您需要的,以便一个组件(tile)的更改影响其他 tile。在 parent.

中输入是否已揭牌的状态
class Board extends React.Component {
    constructor(props) {
        super(props);
        game_logic.initalizeGame(8,8,10);
        game_logic.createGame();
        this.state = {
            height: 8,
            width: 8,
            num_mines: 10,
            revealed: Array.from(
                { length: 8 },
                () => new Array(8).fill(false)
            );
        }
    }
    handleReveal = (x, y, visited = new Set()) => {
        const tileKey = x + '_' + y;
        // if out of bounds, or if visited before, don't do anything
        if (visited.has(tileKey) || game_logic.tile_values[x]?.[y] === undefined) return;
        visited.add(tileKey);
        const isZero = game_logic.tile_values[x][y] === 0;
        this.setState({
            ...this.state,
            revealed: this.state.map(
                (row, i) => i !== x
                    ? row
                    : row.map(
                        (tileState, j) => y === j ? true : tileState
                    )
            )
        });
        if (isZero) {
            handleReveal(x - 1, y);
            handleReveal(x + 1, y);
            handleReveal(x, y - 1);
            handleReveal(x, y + 1);
        }
    };

现在 parent 组件有 handleReveal,将其传递给每个图块。单击左键时,调用向下传递的 handleReveal,并让 children tiles 通过检查 parent 的 revealed 状态来决定要渲染的图像X 和 Y 是真还是假。

Tiles 可能不应该声明自己 除了 它们是否被标记。 imgSrc 可以直接从道具中确定,value 也是如此。最好不要在 parents 和 children 上重复状态 - 这样做会使事情变得混乱且难以处理,尤其是在更新时。