This course has been updated! We now recommend you take the State Machines in JavaScript with XState, v2 course.
Transcript from the "Actions in XState" Lesson
[00:00:00]
>> Now we're going to be talking about actions, If you've used Redux or NgRx or ViewX or any of those similar libraries before, actions might mean something different. But in state machine lingo an action is a side effect, it's something that's fire and forgets something that happens, and you could consider these effects to be the output of the state machine.
[00:00:24] So as you're moving through the state machine, things might happen, and we want to keep track of what things could possibly happen, when you transition between states. If you go to the Wikipedia article for finite state machine over here, You'll see that in concepts and terminology, there's actions which represents what side effects are done when you either enter a state or you exit a state, or you take a transition.
[00:00:58] So in short, with state machines, consider actions to be your side effects, so there's three types of actions, or three locations of actions that could happen in your state machine. The first one is transition actions, so these are actions that are executed whenever you take a transition. For example, if you go from idle to FETCH, then this fetchdata action is going to occur.
[00:01:26] Now, when you go from idle to FETCH, you land on the pending state, and there we have what's called an entry action. These are actions that are taken whenever a state is entered, so when you enter the pending states, in this case we are going to show a spinner and that's going to be the side effect that's executed once you get into that state.
[00:01:48] Now once you exit that state, and exiting a state means transitioning out of the state and into a new state, then the exit actions are going to occur. So in this case, when we go from pending to resolved on the RESOLVE events, the hide spinner action is going to occur.
[00:02:08] So let's talk about action order for a minute, let's say that we're on the idle state. When we go from idle to pending, the first thing that's going to happen and you could follow the arrow, which makes it a little bit more intuitive, is this fetchdata action is going to happen.
[00:02:29] Once you reach pending, this showSpinner action is going to happen, so this action is taken first, and then this one. And once the RESOLVE event happens, then we exit this pending state so this hideSpinner action is going to occur. Now as far as action order, again following the arrows, the first thing that's going to happen, is the exit action of the state that you're currently on, is going to be taken first.
[00:02:59] And then the transition action is going to occur, and entry action of the state that you arrive on, is going to happen. So the order goes, exit actions, transition actions then entry actions. However in general since actions are side effects that are just fire and forget, we don't want to depend on action too much.
[00:03:21] If you find yourself depending on certain actions to occur before another action, then that's a sign that you might want some model it as extra states instead of just implicitly relying on this action order to occur. So in Xstates, we have those three places where you could add extra actions in a transition, you could add it to the actions property.
[00:03:49] And in action function is going to be a function that takes in the context which we'll get into in a minute, and the event and you could do whatever you want inside that action because, again, it's considered a side effect. Inside each state node, you have an entry property, which could contain one or more actions that are executed once you enter that state.
[00:04:12] And so we have entry, and we also have exit over here. Now a better way to represent these actions is to use or to separate them out from inline functions, into their own functions. And in this case, we're using the ES6 that arrow syntax for the functions, since we're just console.logging something, we don't necessarily need the context or the events.
[00:04:41] So this enter active action is going to log into the active, and we could just put that right over here, and it's a bit cleaner. And it also shows up really well in the visualizer which we'll see in a minute. Now, you could also have multiple actions as well, so one syntax that is sort of a syntax trigger for Xstate, is that you could specify one or more actions either as a single action, or an array of actions.
[00:05:11] If you give it an array, it's going to execute both of these actions, again, don't depend on the order. Just assume that interactive and send telemetry, are going to be executed at exactly the same time, because they will be. So, when you enter active both these events will happen, and then once you click this clickActive, click active action is going to occur.
[00:05:38] And we also have this exitActive which is going to occur before, clickActive, and it's gonna go into inactive. It might make more sense if we actually show this in the visualizer, so, we're going to go ahead and do that, I'm going to copy this, right into the visualizer.
[00:06:07] Okay, over here, that's console.log sending telemetry, and hopefully, this is correct great. All right, so now you could see when you click the states tab, once we entered the initial state which is active, we're going to execute two actions, the enterActive, and the sendTelemetry action as well. Once we click think about whats going to happen, the first thing that will happen is we're going to exit active, so we're gonna call the exitAction, and we're going to execute it, then we're going to execute the clickActive action.
[00:06:52] And then we're going to enter inactive, so we're going to execute this enterinactive action. So once we click, that's exactly what happens. We have exitInactive, clickInactive and enteriInactive. Now, the way to get to show up on the visualizer is to convert those action functions to strings such as enterActive, clickActive, exitActive.
[00:07:21] And you can think about this as if you were trying to make a JSON version of your machine. So, we could specify the names of the actions that are going to be executed right here in the machine definition, and as a second argument, we pass an options object.
[00:07:37] And this object allows you to specify different things such as, the actions. So, we could say, this sentTelemetry action which we reference up here, as the string, refers to this side effect, which is sending telemetry. Same thing with enterActive, clickActive, and all of the other actions.