Build a Dynamic Grid challenge
A machine-coding task: render an N×M grid where N and M (and often cell state) are dynamic. Key points: derive the grid from state (a 1D or 2D array), drive columns with `grid-template-columns: repeat(N, 1fr)` from a variable, handle cell clicks immutably by index, keep keys stable, and lift configuration (size) to controlled inputs. Watch for re-render cost on large grids.
"Build a dynamic grid" is an open machine-coding prompt — the interviewer watches your component structure, state modeling, and React fundamentals. Common variants: a grid whose size is configurable, cells that toggle on click, a "light box" puzzle, Conway's Game of Life.
Model the state first
Decide your data shape before writing JSX:
// Option A: 1D array, index = row * cols + col (simple, fast)
const [cells, setCells] = useState<boolean[]>(() => Array(rows * cols).fill(false));
// Option B: 2D array (intuitive, but harder to update immutably)
const [grid, setGrid] = useState<boolean[][]>(...);1D is usually cleaner for updates. Keep rows/cols as their own state, driven by inputs.
Drive the layout from the variable
<div
className="grid"
style={{ gridTemplateColumns: `repeat(${cols}, 1fr)` }}
>
{cells.map((on, i) => (
<button
key={i}
className={on ? "cell cell--on" : "cell"}
onClick={() => toggle(i)}
aria-pressed={on}
/>
))}
</div>.grid { display: grid; gap: 2px; }
.cell { aspect-ratio: 1; border: 1px solid #ccc; }CSS Grid + grid-template-columns: repeat(N, 1fr) from state is the cleanest dynamic-grid mechanism.
Update immutably
function toggle(i: number) {
setCells((prev) => {
const next = [...prev]; // copy — never mutate prev
next[i] = !next[i];
return next;
});
}Use the functional updater so it's correct under batching, and copy before writing.
Controlled configuration
<input type="number" value={rows} onChange={(e) => setRows(+e.target.value)} />Resizing should re-initialize the cells array (a useEffect on [rows, cols], or derive size into a key).
Things the interviewer is checking
- State shape — did you pick something easy to update immutably?
- Immutability — copy, don't mutate; functional updater.
- Keys — stable (
iis acceptable here since cells aren't reordered). - Layout — Grid driven by a variable, not hardcoded.
- Accessibility — cells are
<button>s,aria-pressed, keyboard-operable. - Performance — for large grids, each toggle re-renders the whole grid. Mention
React.memoon the cell, oruseReducer, and that for very large grids you'd virtualize or move to canvas.
Common follow-ups
- "Now make cells toggle their neighbors" (lights-out puzzle).
- "Add Game of Life rules" — a tick function over the array.
- "10,000 cells — it's slow" — memoize cells, or canvas, or virtualize.
Senior framing
The senior approach is state-shape-first: choose a representation that makes the required updates trivial and immutable, derive the layout and rendering from it, and proactively name the re-render cost on large grids with concrete mitigations (memo, reducer, virtualization, canvas). Jumping straight to JSX without modeling state is the junior tell.
Follow-up questions
- •Why is a 1D array often easier than a 2D array for grid state?
- •How would you optimize a 100×100 grid where one cell toggles?
- •How would you implement 'clicking a cell toggles its neighbors'?
Common mistakes
- •Mutating the state array directly instead of copying.
- •Hardcoding the column count in CSS instead of driving it from state.
- •Not using the functional state updater.
- •Re-rendering all cells on every toggle with no memoization for large grids.
Edge cases
- •Resizing the grid must reconcile or reset the cell data.
- •Very large grids: DOM node count alone becomes the bottleneck → canvas.
- •Index keys are fine here only because cells never reorder.
Real-world examples
- •Game of Life, lights-out puzzles, pixel editors, seating charts, calendar grids.