I am trying to build a maze generator using react that displays every step of the generation (every wall opening). So far I have a grid component (parent) and a cell component (child)
The grid component generates a m * n matrix filled with cell components. A cell has four walls that can be removed or added (css border- property).
I am at the part where I want to trigger the maze generation (by clicking a button). I think it should sit in the grid component since it has the grid of cells, but I can't figure out how to change the cell's state from the grid. I get that in some scenarios you want to keep the child's state in the parent but keeping a state for every single wall of every single cell within the grid seems weird.
The algorithm picks a random cells and opens the walls from the current cell to the chosen cell. Can I achieve such a behavior from the grid or do I need to put my mazeGeneration function somewhere else?
Thank you
Here's my current code:
GridComponent
const Grid = (props) => {
const generateGrid = () => {
let grid = [];
for (let i = 0; i < nbRows; i++) {
let curRow = [];
for (let j = 0; j < nbCols; j++) {
curRow.push(
<Cell
key={`[${i}][${j}]`}
posX={i}
posY={j}
cellSizeInPx={cellSizeInPx}
className={'cell'}
/>)
}
grid.push(curRow);
}
return grid;
}
const { nbCols, nbRows, cellSizeInPx } = props;
const [grid, setGrid] = useState(generateGrid);
return (
<table className='grid' >
<tbody>
{
grid.map((row, idx) => {
return <tr key={idx}>{row}</tr>
})
}
</tbody>
</table>
)
}
CellComponent
const Cell = (props) => {
const [hasTopWall, setTopWall] = useState(true);
const [hasRightWall, setRightWall] = useState(true);
const [hasBottomWall, setBottomWall] = useState(true);
const [hasLeftWall, setLeftWall] = useState(true);
const { className, posX, posY } = props
return (
<td
className={`cell
${hasTopWall ? "top" : ""}
${hasRightWall ? "right" : ""}
${hasBottomWall ? "bottom" : ""}
${hasLeftWall ? "left" : ""} `}
>
</td>
)
}
export default Cell;
Cell.css
.cell {
width: 20px;
height: 20px;
}
td {
padding: 0;
}
.top {
border-top: 1px solid rgb(175, 216, 248);
}
.right {
border-right: 1px solid rgb(175, 216, 248);
}
.bottom {
border-bottom: 1px solid rgb(175, 216, 248);
}
.left {
border-left: 1px solid rgb(175, 216, 248);
}