Where I try to learn XState in 75 minutes

javascript learning

Part one

Let’s try something. I have a bit more than an hour in front of me, and I’ve been wanting to learn XState, a JavaScript state machine library. I had one exercise in mind: porting the hand-rolled state code in the small click precision game I built last year to XState, if possible.

How much can I do in an hour or so?

13:50 Go to the GitHub repo and check if I have the code locally.

13:55 Tangent: to update dependencies (including a few major versions for rollup plugins). Things fail. I end up getting the package.json and rollup.config.js from the latest version of the basic Svelte app template. Still failing. Woops.

14:15 Turns out sirv-cli is starting a server on port 5000 mais that’s already taken and it doesn’t realize it. So I was seeing a “403 Forbidden” page from a different, already-running web server. Eh.

14:20 PORT=4000 npm run dev and we’re good. Push an update commit. Close 8 tabs.

14:25 Let’s make coffee.

14:30 Opening the XState docs. At the half-time mark. Don’t want to be negative here, but it’s not looking good.

14:31 Coffee is boiling (Bialetti Moka Express pot).

14:33 A quick refresher on what my tiny game does. There’s a square playground where a smaller square appears at a random place, and you have to click that smaller square before it disappears. The main logic is in src/Playground.svelte. By default the game plays 20 turns, and each turn has a few steps that are needed to trigger animations (by inserting elements or classes, it was hacky and a pain to get working, CSS animations are not my favorite thing ever).

14:40 There’s a bit of application state to say if we’re setting up a game, playing, or showing scores. When playing, the main states are defined as objects with duration and other parameters, and a next key telling which is the next phase:

export const PLAY_PHASES = {
  START: {
    next: "COUNTDOWN_3",
  },
  COUNTDOWN_3: {
    next: "COUNTDOWN_2",
  },
  COUNTDOWN_2: {
    next: "COUNTDOWN_1",
  },
  COUNTDOWN_1: {
    next: "TURN",
  },
  TURN: {
    next: "COOLDOWN",
  },
  COOLDOWN: {
    next: "TURN",
  }
};

So we start at the START phase, go to COUNTDOWN_3, COUNTDOWN_2, COUNTDOWN_1, then TURN, then COOLDOWN, and then back to TURN, etc.

Is that a kind of state machine? I have no idea. Let’s look at the XState docs.

14:47 Super quick start section. They have a toggleMachine where you toggle between an “active” and “inactive” state. Okay, simple enough.

14:50 The next example is more complex, it as idle, loading, resolved and rejected states, and inside the loading state it’s performing a HTTP request. The code was scary at first, but playing with the interactive state chart that lets you trigger the FETCH event (to go from idle to loading) by clicking it? That helped. And I’m starting to see the concepts (states, events, states that can invoke code and react to the result…).

Sadly the example doesn’t work fully because the request fails (redirects from https to http, then it’s blocked as mixed content). So I can see this flow:

  1. state: idle
  2. event: FETCH (I clicked)
  3. state: loading
  4. state: rejected
  5. event: FETCH (I’m trying again)
  6. state: loading
  7. state: rejected

Hey, it’s demonstrating 3 states out of 4, not bad.

15:05 Alarm rings.

What did I learn so far?

Part two

I have a bus to catch, so that will be another day.