Skip to content

Traffic Light State Machine

A traffic light state machine that cycles through Red, Yellow, and Green states, demonstrating a state machine with multiple distinct states in a defined sequence.

This example demonstrates:

  • Defining states with typed data using defineStates()
  • Creating a machine with multiple distinct states (Red, Yellow, Green)
  • Cyclical transitions between states in a defined sequence
  • State-based UI rendering with conditional styling
  • Type-safe state handling throughout the application

Unlike the counter example which focuses on state data, or the toggle example with just two states, this traffic light example shows how to model a system with a clear sequence of states and associated messages.

import { defineStates, matchina } from "matchina";
const states = defineStates({
Red: () => ({ message: "Stop" }),
Yellow: () => ({ message: "Prepare to stop" }),
Green: () => ({ message: "Go" }),
});
export const createTrafficLightMachine = () => {
return matchina(
states,
{
Red: { next: "Green" },
Yellow: { next: "Red" },
Green: { next: "Yellow" },
},
"Red"
);
};
export type TrafficLightMachine = ReturnType<typeof createTrafficLightMachine>;
  • Each state (Red, Yellow, Green) represents a discrete condition of the traffic light
  • The next transition allows cycling through the states in the proper sequence
  • The view component uses state.match() to elegantly handle different UI states
  • Pattern matching is type-safe and ensures all states are handled

This traffic light example demonstrates the core components of a Matchina state machine:

  1. State Definition: We define three states (Red, Yellow, Green), each with associated data (a message).

    const states = defineStates({
    Green: () => ({ message: "Go" }),
    Yellow: () => ({ message: "Prepare to stop" }),
    Red: () => ({ message: "Stop" }),
    });
  2. Machine Creation: The state machine is created using matchina(), which takes:

    • The defined states
    • A transition map describing allowed state changes (using the next event)
    • An initial state ("Red")
    return matchina(
    states,
    {
    Green: { next: "Yellow" },
    Yellow: { next: "Red" },
    Red: { next: "Green" },
    },
    "Red"
    );
  3. State Transitions: The machine cycles through states when machine.next() is called.

  4. State Access: The current state is accessed using machine.getState(), which provides:

    • The state key (currentState.key)
    • Type-safe access to state data (currentState.data.message)
    • Methods for state checking (currentState.is("Red"))
  5. Type Safety: TypeScript ensures type safety throughout, preventing invalid state references.

For a minimal introduction, see the Quick Start.

This basic implementation can be extended in several ways:

  • Add automatic transitions using lifecycle hooks and timers
  • Implement pedestrian crossing controls
  • Add special states like “flashing yellow” for low-traffic periods

Check out the Extended Traffic Light Example to see the first two extensions implemented (automatic transitions and pedestrian crossing).

Now that you’ve seen state machines with varying complexity, you might want to explore: