A state machine is a standardized way of defining and enumerating all possible (hence "finite") states of a system. It also defines and enumerates the transitions from one state to another. These transitions are triggered by sending events to our machine. Simply put, it is possibly the most robust way to define and manage state in an application.
In this lesson, we'll build a basic elevator state machine. An elevator has three possible states: stopped, moving up, or moving down. We'll define these states, their transitions, and send events to change our state.
We'll also cover using xstate
machines in strict mode, as well as adding a key
property to make our error messages better.
Instructor: [00:00] Conceptually, a simple state machine is an object that contains a state's property that enumerates all the possible and hence finite states of a system and an initial property to define our initial state. To create a machine using xstate, we first import the machine constructor from the library.
[00:19] Next, we're going to create a machine instance by configuring it. Let's create a machine for an elevator. An elevator, and by this I specifically mean the box part contained in an elevator shaft that you and I stand in and remain awkwardly silent for the duration of the trip as three possible states.
[00:38] It can be stopped, it can be moving up, or it can be moving down. Our elevator will be initialized with the state of stop. I left our states empty for the time being just to show their enumeration.
[00:52] In order for our machine that work though, we have to add transitions in the each one of our states using the ON property. Our transitions define how we move from one state to the next.
[01:03] For example, an elevator that is stopped can only transition into moving up or moving down. To do this, we create the ON property, we make an object, we define our event names, and by convention we capitalize these, and the value is the key of our next state.
[01:22] To finish outer elevator, an elevator moving up can only be transitioned into being stopped or moving down. An elevator moving down can only be transitioned into being stopped or moving up.
[01:34] Now that, we've defined all the possible transitions in our machine. Let's create a function that allows us to send events to our machine and log out the current state.
[01:44] Now, a state machine doesn't actually store a state. It simply defines an enumerated state. We need to save our state elsewhere. To do this, I'll create a variable called current elevator state.
[01:57] I'll set to the initial state of our elevator. Now, I'll create a function that receives an event as an argument and uses the transition method on our machine in order to fire that transition.
[02:09] Transitions are pure function. We need to handle the state as its first argument and the event as the second argument. Lastly, we'll log out our current state after the transition has happened.
[02:21] Now that, we have our function. Let's use it a few times. Let's move our elevator up, down, and then stop it. Let's log this out in the terminal and see that our states updated.
[02:35] We'd see we move from a stop to an up state in the first one, from up to down in the second, and from down to stop in the third. Now, this doesn't prevent us from sending events that don't exist as possibilities in our machine like so.
[02:51] If I log this out, we'll see that the state doesn't change. See that in the fourth one, it remained in a stopped state. xstate machines provide as an option that put them into strict mode.
[03:02] What this would do is throw an error any time we try to send an event that's not one of the enumerated possibilities of the current state. Let's go up to our machine and put it in the strict mode, save it, and we'll come back down.
[03:16] When we run this in our terminal, we'll see that an error is thrown. If we scroll up a bit, we could see that it threw an error on our fourth one, and that error was machine, machine does not accept event foo.
[03:29] This points us to one more property we can add to our machines. This property is derived from the key property of our machine. By default, it's machine in parentheses, but we might want to give our machines a better names, so that we can identify it more easily an error messages.
[03:46] I'm going to go up to the top again. I'm going to give it a key property of elevator. We'll save this. We'll clear a terminal. Make it a little bit easier to read. Then, we'll run our file once more and see as somewhat better error message.
[04:02] Scrolling up and we see error machine elevator does not accept event foo.