Check out a free preview of the full State Machines in JavaScript with XState, v2 course

The "Actions 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 student's questions regarding if raise can be used to send a child state to a parent state, when side effects should change, if actions are executed in sequence, and will raise SKIP only execute when the loading sequence is done. Why there are multiple ways to do the same thing even if there is a preferred way and how raise compares to send are also covered in this segment.


Transcript from the "Actions Q&A" Lesson

>> One of the questions asked, was raised, sounds like a way for a child state to send events to the parent states. Can I use it for that, too? The short answer is yes, and that's exactly what we're going to be doing in the compound states lesson. And so again, raising an event makes it so that even if the child is handling a different event but it needs the machine to behave as if another event handled in potentially a different state.

But with handle it then raising event basically lets you abstract that away. So updates should not be performed solely on the value of the target, they should only be performed on an action. So I'm interpreting updates to mean what is shown in the UI, and also what side effects are executed.

Side effects which are things that are done externally, those should always be done in actions. Now the way that UI changes, we could have just what we consider to be implicit actions. And react, and other frameworks sort of just abstract this away for you, because anytime we're changing something in the UI, that is actually an action or side effect.

It's just that we abstract that away in a declarative view layer, which is what react and view and other popular frameworks provide. So over here we're just synchronizing the UI to the state, and that's based on the actual state, like Loading, Play, Pause. Now if we want to get really granular, we could do something like when we enter the loading state, show the Loading button when we exit the loading state, hide the loading button.

But that's gonna get very verbose very quickly. And so that's, again, why frameworks exist, and why right now we're just synchronizing the state with those attributes. So it's up to you to decide whether you want to represent updates as actions, or as just synchronizing with state. But yeah, just keep in mind that external side effects should be done in actions, or actions executed in sequence will Raise skip, only start executing after dislike song is done.

So, yeah, the way that this works, and, in fact, I'm gonna take this and I'm gonna copy it. And we are going to put this inside the visualizer so that we could just take a look at it. Let's import Raise from next day live actions. All right, so the way that the actions are going to be executed, for example, when we're in the loading state, and the loaded event happens, now we're in the playing states, and let's say we want to skip this song.

What's gonna happen is that skip song, because it's a transition action, that's going to be executed first. And since we're exiting the playing states, now the Pause Audio action is going to happen. I'm pretty sure, and also you should not be super dependent on the order of actions.

Assume that the actions are going to be run at the same time even though they're not run concurrently, just don't depend too much on the order of actions. If you do want actions to run in sequence, like this action needs to run before this one, then that's something that should be represented in separate states.

So that it is 100% clear and precise which actions are going to execute when. Another question, I'm curious why X state has many ways to do the same thing. It seems there's a preferred way, so why allow so many ways such as inline actions versus using with config, etc.

So part of this is just the evolution of the X state. It's a state machine and state chart's library that's about six years old. So it's gone through a lot of iteration, and also it's about the purpose of what you use it for. So X state is meant to be like this hybrid of allowing you to model your states and your logic, and also allowing you to implement it.

So just like we're doing in this lesson, we're implementing our actions in the nice and quick way. Like, I honestly appreciate that I could just type in whatever action, and worry about the implementation later. Because this is something that can be immediately visualized, handed off to someone without having to think I actually didn't implement that yet so I can't share with you the diagram or the model that we're gonna be programming against.

So, I also want to say, too, that if X state only allowed one way, it would be very verbose. So for example, actions, let's say that every action required a type, which this is what it's converted to, and the actions can have multiple actions inside of them. So this is how you would have to type everything, and so for example this target, or yeah, the target is already playing this, you'd have to put it in an array.

So I do see the benefit of staying consistent, and that's something that I've heard in the past. However, as a prototyping tool, that becomes a friction point. And so that's why X state does have a couple of different ways of doing the same thing. In the future with X state version 5 and other helper libraries on top of X state, it's going to make it easier to enforce a single way of doing something.

And also, we are going to be updating the docs and we're gradually doing so already, where we only emphasize one way of doing things such as typing your actions, or putting your states in. But the key is that we want you to be able to move fast with actually modeling your application, instead of having to drown yourself in a bunch of syntax that you might not need.

Another question in the chat, can you recap what Raise does in how it compares to send? And so that's something that we're also going to be talking about in the last lesson, or second to the last lesson, on actors, is that Raise is a machine sending events to itself.

Send is either a machine sending an event to itself, or sending an event to another machine. I recommend you use Raise if you're sending events to yourself, and you Send if you're sending events to another actor, or machine which is an actor. So, that's in short the difference there, and in version 5 we're going to consolidate it so that Send becomes Sent To, and really becomes an action for sending to a separate actor.

And encouraging the use of rays in order to send in events to the machine itself. And another question, does Raise work with parallel states, too? We're gonna be talking about parallel states in the future lesson, but yes, Raise works everywhere.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now