I’m building a React application that asks the user for an input, and if correct (enter “3”), we render a 10×10 grid of buttons, each tied to a click handler.
When any button is clicked, it should print to the console the internal representation of the 2d grid array, ie , the state value of grid
.
Here is the basic code:
The Grid
component, which takes a 2d grid array, and creates a button array. Each cell
is { onClick: (...) }
const Grid = ({ grid }) =>
grid.flat().map((cell, index) => (
<button key={index} onClick={() => cell.onClick(index)}>
{index}
</button>
));
Here is the Input
component, which uses setInput
from parent
const Input = ({ setInput }) => {
const [_input, _setInput] = React.useState("");
return (
<div>
<input onChange={(e) => _setInput(e.target.value || "")} />
<button onClick={() => setInput(_input)}>Play</button>
</div>
);
};
Here is the main App
component. It renders the Input
, and based on a useEffect
hook, if the input is valid (its 3), it updates the valid
state, and also should create the grid
state.
const App = () => {
const [valid, setValid] = React.useState(false);
const [grid, setGrid] = React.useState([]);
const [input, setInput] = React.useState(null);
const reveal = () => {
console.log("grid is ", grid);
};
const createGrid = () => {
if (input !== "3") return [];
const arr = Array.from({ length: 10 }, () =>
Array.from({ length: 10 }, () => ({
onClick: () => reveal(),
}))
);
console.log("setting grid to ", [...arr]);
setGrid([...arr]);
};
React.useEffect(() => {
setValid(input == "3");
createGrid();
}, [input]);
return (
<div>
<Input setInput={setInput} />
{valid && <Grid grid={grid} />}
</div>
);
};
export default App;
I can see that when the component is initially rendered, and we enter “3”, the grid state does get set, but when I click on a button, the reveal
function prints that the grid state is []
. Why is this happening?