Check out a free preview of the full State Machines in JavaScript with XState, v2 course
The "State Machines Q&A" Lesson is part of the full, State Machines in JavaScript with XState, v2 course featured in this preview video. Here's what you'd learn in this lesson:
David answers students' questions regarding if creating state machines is the JavaScript implementation of the state pattern and if XState is compatible with state machines written in SCXML. Questions regarding if there is a reason to name states in all capitals, how to determine what states should be named, and if a state can receive multiple events at the same time are also covered in this segment.
Transcript from the "State Machines Q&A" Lesson
[00:00:00]
>> One question was, can we say that creating state machines like this is the JavaScript implementation of the good old state design pattern? And so the short answer is yes. The state pattern, if you remember your gang of four design patterns, the state pattern is very similar to a finite state machine.
[00:00:20]
So in the state pattern if you don't know, a state pattern defines an object that can change its behavior. And so for example, in this application, if we were to represent this as a class, we might have a loading behavior, which is going to be a separate function that describes this is what should happen when I'm loading.
[00:00:42]
But we're also giving it the ability to change behaviors as well. One good way that you could do this in your app and sort of get closer to that state design pattern is by separating this in a function. So let's say we have this case, let's go over here.
[00:01:00]
So we have this, if event type is loaded, return the playing state. Otherwise, we just want to return the normal state. And so we could have something like function loading behavior in which we know that if we're in this loading behavior, we're going to have the state value as loading.
[00:01:26]
And so instead of having to switch on the state, we could just pop this function in. And so we could just cut this, put there, otherwise return the state. And so now over here we could just return loadingBehavior(state, event). So like I said, this gets closer to that state design pattern.
[00:01:55]
The only difference between this state's design pattern and using a finite state machine is that the state design pattern says the machine, or sorry, the class or object, or whatever you wanna call it, can change its behavior at will. With finite state machines, the only way a behavior can change is due to an event.
[00:02:15]
And I promise you that's a lot more flexible than it sounds. But it's a good constraint to keep in mind, that you shouldn't be arbitrarily changing behavior, but instead make it due to events. So yea, if you want to refactor this as a separate behavior function, then that's definitely one way to do it.
[00:02:38]
Does XState allow you to import state machines written in SCXML as XState compatible state machines and export them to, or as SCXML state machines for state machine related tools in libraries? So yeah, that's jumping ahead a little bit. But by SCXML, this is a a specification by the W3C.
[00:02:59]
And it's a state machine notation that is represented, as you probably guessed, in XML. And so this standard, if you read it all in, it's a pretty big read, it is going to feel very close to XState, and that's on purpose. XState implements SCXML and the algorithms. And one of the long-term goals of XState is to be compatible with SCXML in general.
[00:03:26]
Currently, we do import SCXML internally for a lot of testing, but there aren't public-facing features that allow you to do this easily. But it is definitely possible. So the takeaway from this question is, if you really want to understand what XState is about more in-depth, I really recommend you read the W3 specification for state chart XML.
[00:03:52]
You're going to find a lot of things in common with XState and this SCXML notation and see inspiration for a lot of XState's API. The question was, is there a reason to name the events in all caps, or as I like to call it screaming case? The short answer is no, you don't need to do it.
[00:04:13]
I like doing it just because it's a visual differentiator between states and events. I know something is an event because it's something that's screaming at me. So I could just quickly scan the page and see, that's an event because it's all in uppercase. But there is no reason that you have to do this.
[00:04:33]
And even myself, I'm finding myself writing lowercase events, like pause, more frequently in my applications. I think the uppercase events name was just something that was started by libraries and Redux, and it became sort of an unofficial convention. If you don't wanna use uppercase, you don't have to.
[00:04:57]
It's not a restriction in XStates or pretty much anything. There's nothing that's checking that all of your state names are uppercase. However, I will say that for future versions of XState, what you should do is like, if you have events that can really be described within a group of events, so let's say that we have audio paused.
[00:05:26]
I really recommend that you separate it with a dot. And that's the one convention that's actually going to be really useful. Because in the future, and this is XState version 5, not XState version 4, you're going to be able to specify wildcard events. And so this basically handles any event that starts with his audio dot.
[00:05:49]
And the delimiter is the dot, so this is also specified in SCXML. So that convention I would recommend, the uppercase convention, you can have your own preference on that. There was a comments that we do have a Stately Discord. And for all questions related to state machines, state charts, the actor model, events-driven architecture, software modeling, and also the tools that we release, it's at discord.gg/xstate, open invitation.
[00:06:25]
I highly recommend that you join this Discord because we are extremely responsive in there and wanna help everyone with all their problems. And there's also so many good ideas and sources of inspiration in the Discord. So if you have any questions or you just wanna chat, feel free to join the Stately Discord, again, at discord.gg/xstate.
[00:06:47]
The question online was, what about naming the actual states over here? How do we determine what these states should be named?. And so for the states, I have two general guidelines. First, you should name it based on what is happening. And you should also name it based on what the behavior should be.
[00:07:08]
So as long as you choose any of those, or ideally a combination of both, you should be safe. So for example, in this state we're asking, what's happening? Well, the song is loading. And now we're asking, what's happening over here? The song is playing. And we're asking, what's happening here?
[00:07:26]
The song is paused. If we were to model something else, like, for example let's say that we're modeling drag and drop, but we're locking to the x-axis or y-axis so you can't move it freely. You could only move it on one of the axes. Then we might have something like, I call it x-axis lock.
[00:07:53]
And so now, this isn't exactly describing what's happening, it's describing a behavior instead. So this x-axis lock is a state that says any event that happens here, we have to lock any positional changes to the x-axis. So again, this is a demonstration of what's happening or what the behavior should be.
[00:08:17]
And so that's how you should describe your states. Can a state receive multiple events at the same time? How does the state transition to the next state? And so with state machines and state charts, the idea is that you always receive events one at a time. So for example, let's say that we spammed this machine in the loading state with five instances of loaded, all being sent at the same time, for whatever reason.
[00:08:50]
Let's say that one of our services is just behaving badly and has some race conditions or something. And we just get multiple events at the same time. So what should happen is those events should be queued up. So we have a queue of events and we pop from the queue each time and we say, okay, let's handle these events one at a time.
[00:09:15]
So in the loading state, we're only going to handle one event, which is loaded, we transition. And once we're on this state, this all happens immediately, by the way, once we're on that state, then the next loaded event will do nothing. Because we're in the playing state and the loaded transition does not exist on that state.
[00:09:38]
So in summary, events are handled one at a time, always.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops