Skip to content

Traffic Light State Machine

Multi-state machine with automatic transitions demonstrating cyclic state flows.

Use Case

This example models a traffic light with a red → green → yellow → red cycle. It demonstrates how to handle multiple states with cyclic transitions, making it useful for:

  • Traffic light controllers
  • Multi-step workflows with repeating cycles
  • Game state loops (menu → playing → game over → menu)
  • Carousel or slideshow controls

Complete Code

import { createMachine } from "xstate";
// Define states
type TrafficState = "red" | "yellow" | "green";
// Define events
type TrafficEvent = { type: "TIMER" };
// Create machine
const trafficMachine = createMachine<TrafficState, TrafficEvent>({
id: "traffic",
initial: "red",
states: {
red: {
on: {
TIMER: "green",
},
},
green: {
on: {
TIMER: "yellow",
},
},
yellow: {
on: {
TIMER: "red",
},
},
},
});
// Usage with timer
let state = trafficMachine.initialState;
console.log(state); // 'red'
// Simulate automatic transitions
setInterval(() => {
state = trafficMachine.transition(state, { type: "TIMER" });
console.log(`Light changed to: ${state}`);
}, 3000); // Change every 3 seconds

Code Explanation

  1. Multiple states - Defines three distinct states ('red', 'yellow', 'green') instead of just two, showing how state machines scale beyond binary toggles.

  2. Cyclic transitions - Each state transitions to the next state in the cycle when receiving a TIMER event, creating a continuous loop.

  3. Timer integration - Uses setInterval to automatically trigger state transitions, demonstrating how external timing mechanisms integrate with state machines.

  4. Deterministic behavior - No matter how many cycles complete, the state is always predictable based on the number of TIMER events received.

Key Concepts

  • Multi-state machines: Not limited to two states - model complex workflows with many states
  • Cyclic transitions: States can form loops, returning to previous states in a predictable pattern
  • External triggers: State machines react to external events like timers, user actions, or network responses
  • Deterministic: Same sequence of events always produces the same sequence of states

Variations

Different timing per state:

const timings = { red: 5000, green: 4000, yellow: 2000 };
let state = trafficMachine.initialState;
function scheduleNext() {
setTimeout(() => {
state = trafficMachine.transition(state, { type: "TIMER" });
console.log(`Light: ${state}`);
scheduleNext();
}, timings[state]);
}
scheduleNext();

Next Steps