Build the classic Snake game as a single React component. A snake crawls a 12x12 grid one cell per tick; arrow keys steer it; eating food grows it and scores a point; running into a wall or your own body ends the game. It's a small game, but it forces two things most timers get wrong: a loop that reads the latest state, and a clean teardown.
The starter App.tsx renders the board in its resting state — a 3-cell snake, one piece of food, score 0, and a Start button — with no logic. Make it playable:
snake (array of {x, y}, head first), food, score, running, and over, all in useState.setInterval(step, 150). Each step computes newHead = head + dir and either ends the game (wall or self), grows (on food), or moves (add head, drop tail).window keydown listener maps arrow keys to a direction — but never one that reverses straight into the neck.keydown sets the direction; the interval, created once, must see that change — a value captured in the interval closure goes stale. Hold the direction in a ref.pop.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.