In the previous lesson, you set up a global store using useReducer and Context. That store gives us state and dispatch anywhere in the app. Today, you will use that setup to control which screen is visible — without React Router. This is a small but powerful pattern: the UI screen is just state (ui.screen), and navigation is just dispatching an action to change that state.
Explanation:
GameProviderwraps the app so all children can access state and dispatch (from the previous lesson’s store).AppContentreadsstate.ui.screenusinguseGameContextand picks which screen to render with a simple switch. No routing library is needed.- The
SafeXcomponents are fallbacks so the app can run even if a screen is missing. In your real project, you will have the actual components. - Changing
state.ui.screentriggers a re-render, which switches the visible screen.
Explanation:
- This component does not know about routing. It simply dispatches
SET_SCREENwith a target screen. App.jsxresponds by rendering the correct screen. This keeps navigation logic centralized and UI components simple.
Explanation:
- The game screen also uses dispatch to move to results or back to the menu.
- Again, there are no direct imports of other screens here — just a state change request. That keeps coupling low and makes testing easier.
Tip: ResultsScreen and SettingsScreen follow the same pattern, each dispatching to go where they need.
You now control navigation through state alone:
Apprenders a screen based onstate.ui.screen.- Screens navigate by dispatching
SET_SCREEN. - No router, minimal coupling, and one source of truth.
This is the core of state-driven view management. You are ready to try it yourself — head to the practice section to wire up interactions and see smooth, reducer-powered navigation in action.
