In the last two lessons, you built the global store with useReducer + Context and used it to drive screen changes. As a quick reminder, our UI now depends on state, and navigation is just dispatching actions. In this lesson, you will shape that state for a real game and set up the reducer to handle the first transitions.
We start by defining constants and a single source of truth for all game data. This makes future updates predictable and testable.
Explanation:
RUSH_DURATIONandMAX_QUEUEare constants that keep magic numbers out of the state.ui.screencontrols which view is visible (from the previous lesson’s pattern).configholds difficulty, queue limits, starting resources, and arrival rates — perfect for tuning without touching UI code.timersmodel the game clock and pause state.resourcesandshophold the core gameplay stats you will read and update in later units.profilepersists player-wide stats; passing into lets you reset a run without losing the player’s progress.
Now wire up the first actions. Keep state updates pure and focused. Each case does one thing, and you can grow this over time.
Explanation:
SET_SCREENchanges onlyui.screen. It keeps the reducer predictable and aligns with the state-driven view approach you used earlier.START_GAMEbuilds a fresh run by callinggetInitialState(state.profile). This resets the run but preserves the player profile. It also setsphasetoPLAYINGand switches the screen togame.- The
defaultreturns the current state untouched, which is required for unknown actions.
You defined a clear, nested game state and a reducer that handles the first two transitions. You now have:
- A single source of truth for timers, resources, shop, UI, and player profile.
- A clean reducer with focused actions for screen changes and starting a new run.
You are ready to practice. In the next section, you will put this structure to work and see how a solid state model makes new features easier and safer to build.
