MCPcopy
hub / github.com/statelyai/xstate / App

Function App

examples/snake-react/src/App.tsx:5–68  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

3import { type Dir, getGamObjectAtPos, snakeMachine } from './snakeMachine';
4
5function App() {
6 const [current, send] = useActor(snakeMachine);
7 const { gridSize, score, highScore } = current.context;
8 const isGameOver = current.matches('Game Over');
9 console.log(current);
10
11 useEffect(() => {
12 function keyListener(event: KeyboardEvent) {
13 const [maybeKey, maybeDir] = event.key.split('Arrow');
14 if (maybeDir) {
15 send({ type: 'ARROW_KEY', dir: maybeDir as Dir });
16 } else if (maybeKey === 'r') {
17 send({ type: 'NEW_GAME' });
18 }
19 }
20
21 window.addEventListener('keydown', keyListener);
22 return () => window.removeEventListener('keydown', keyListener);
23 }, [send]);
24
25 return (
26 <div className="App">
27 <header>
28 <h1 style={{ marginBottom: 0 }}>XSnake</h1>
29 <p style={{ margin: 0 }}>Snake with a sweet twist, built with XState</p>
30 </header>
31 <p style={{ fontSize: '1.2em', marginBottom: 0 }}>
32 {isGameOver ? 'Game Over!' : '\u00A0'}
33 </p>
34 <p>
35 Score: {score}
36 <br />
37 High score: {highScore}
38 </p>
39 <div
40 className="grid"
41 style={{
42 gridTemplateColumns: `repeat(${gridSize.x}, 1fr)`,
43 gridTemplateRows: `repeat(${gridSize.y}, 1fr)`
44 }}
45 >
46 {Array.from({ length: gridSize.y }).map((_, row) =>
47 Array.from({ length: gridSize.x }).map((_, col) => {
48 const { type, dir } =
49 getGamObjectAtPos(current.context, { x: col, y: row }) || {};
50 return (
51 <div className="cell" key={`${col} ${row}`}>
52 <span
53 role="img"
54 aria-label={type}
55 className={type}
56 data-dir={dir}
57 />
58 </div>
59 );
60 })
61 )}
62 </div>

Callers

nothing calls this directly

Calls 4

useActorFunction · 0.90
getGamObjectAtPosFunction · 0.90
addEventListenerMethod · 0.80
removeEventListenerMethod · 0.80

Tested by

no test coverage detected