I'm attempting to build a Minesweeper game as practice using React. I have a main Minesweeper.js file with all of the functionality.
export class Tile {
constructor(board, pos) {
this.board = board;
this.pos = pos;
this.bombed = false;
this.explored = false;
this.flagged = false;
}
adjacentBombCount() {
let bombCount = 0;
this.neighbors().forEach(neighbor => {
if (neighbor.bombed) {
bombCount++;
}
});
return bombCount;
}
explore() {
if (this.flagged || this.explored) {
return this;
}
this.explored = true;
if (!this.bombed && this.adjacentBombCount() === 0) {
this.neighbors().forEach(tile => {
tile.explore();
});
}
}
neighbors() {
const adjacentCoords = [];
Tile.DELTAS.forEach(delta => {
const newPos = [delta[0] + this.pos[0], delta[1] + this.pos[1]];
if (this.board.onBoard(newPos)) {
adjacentCoords.push(newPos);
}
});
return adjacentCoords.map(coord => this.board.grid[coord[0]][coord[1]]);
}
plantBomb() {
this.bombed = true;
}
toggleFlag() {
if (!this.explored) {
this.flagged = !this.flagged;
return true;
}
return false;
}
}
Tile.DELTAS = [[-1, -1], [-1, 0], [-1, 1], [ 0, -1],
[ 0, 1], [ 1, -1], [ 1, 0], [ 1, 1]];
export class Board {
constructor(gridSize, numBombs) {
this.gridSize = gridSize;
this.grid = [];
this.numBombs = numBombs;
this.generateBoard();
this.plantBombs();
}
generateBoard() {
for (let i = 0; i < this.gridSize; i++) {
this.grid.push([]);
for (let j = 0; j < this.gridSize; j++) {
const tile = new Tile(this, [i, j]);
this.grid[i].push(tile);
}
}
}
onBoard(pos) {
return (
pos[0] >= 0 && pos[0] < this.gridSize &&
pos[1] >= 0 && pos[1] < this.gridSize
);
}
plantBombs() {
let totalPlantedBombs = 0;
while (totalPlantedBombs < this.numBombs) {
const row = Math.floor(Math.random() * (this.gridSize - 1));
const col = Math.floor(Math.random() * (this.gridSize - 1));
let tile = this.grid[row][col];
if (!tile.bombed) {
tile.plantBomb();
totalPlantedBombs++;
}
}
}
lost() {
let lost = false;
this.grid.forEach(row => {
row.forEach(tile => {
if (tile.bombed && tile.explored) {
lost = true;
}
});
});
return lost;
}
won() {
let won = true;
this.grid.forEach(row => {
row.forEach(tile => {
if (tile.flagged === tile.revealed || tile.flagged !== tile.bombed) {
won = false;
}
});
});
return won;
}
}
Then I have three React components: Board.jsx
import React from "react";
import Tile from "./tile";
class Board extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div>
{this.props.board.grid.map((row, idx) => {
return (<div key={idx}>
{row.map((tile, idx) => {
return (
<div key={idx}>
<Tile
tile={tile}
updateGame={this.props.updateGame}/>
</div>
)
})}
</div>)
})}
</div>
)
}
}
export default Board;
Tile.jsx
import React from "react";
class Tile extends React.Component {
constructor(props) {
super(props)
this.checkState = this.checkState.bind(this)
}
checkState() {
console.log(this)
if (this.props.tile.bombed) {
return "💣"
} else if (this.props.tile.explored) {
return (this.props.tile.adjacentBombCount())
} else if (this.props.tile.flagged) {
return "⚐"
} else {
return ""
}
}
render() {
return(
<div>{this.checkState()}</div>
)
}
}
export default Tile;
and finally a Game.jsx
import React from "react";
import * as Minesweeper from "../minesweeper"
import Board from "./board";
class Game extends React.Component {
constructor(props) {
super(props);
let board = new Minesweeper.Board(10, 5)
this.state = {
board: board
}
this.updateGame = this.updateGame.bind(this);
}
updateGame() {
}
render() {
return(
<Board
board={this.state.board}
updateGame={this.updateGame}/>
)
}
}
export default Game
Within Tile.jsx, I want the render to display adjacent bomb counts using the function from the main Tile js class (in minesweeper.js). This function is accessible when I first render my Tiles as React Components; however, if I change something (by going into components and updating), the function is no longer accessible. To help explain, here is the console.log of this.props.tile
on the first render:
However, after re-rendering from updating a component, this is what this.props.tile
looks like .
Therefore, it will cause an error when I try to add the bomb count, as it cannot find the function. Can someone explain why the function is disappearing and how I can access it when Components change? Thanks!
This was an issue with the React DevTools specifically, and it will be addressed in an update, see: https://github.com/facebook/react/issues/24781