# Webinar: Get started with XState v5

Canonical: https://davidk.dev/talks/webinar-get-started-with-xstate-v5/
Video: https://www.youtube.com/watch?v=TRVjeil-y74
Speaker: David Khourshid (@DavidKPiano), creator of XState
Type: Webinar · Event: Stately webinar · Year: 2023 · Duration: 1:13:11 · Views: 11268 (as of 2026-10-19)
Topics: XState, Actor model, TypeScript, Event-driven architecture

## Summary
We are the Stately team and this is our very special XState version 5 webinar. Every actor has its behavior that could be controlled by a state machine.

## Key takeaways (quoted from the transcript)
- We are the Stately team and this is our very special XState version 5 webinar. (0:00)
- Every actor has its behavior that could be controlled by a state machine. (15:00)
- One huge difference and the reason why it's Stately AI inspect is because we're going to have an API that lets you basically inspect anything, even if it's not XState. (44:00)
- Instead of passing a string over here, the guard type is to do is completed and it expects parameters, too. (53:00)
- Going with that inversion of control, you're going to say these actions expect these parameters instead of these actions expect this specific type of output from the events. (59:00)
- If you wanted to get started quickly first of all the API you just import create machine and create actor and that hopefully this webinar showed that's really all you need. (1:05:00)

## Chapters
- 0:00 Introduction
- 6:00 Course, you could npm install XState, yarn add XState…
- 9:00 To do added, we know that our next state is going…
- 36:00 Mateusz right now is working on basically getting the machine extractor…
- 38:00 If I take this fetch logic, and bring it over here…
- 41:00 Adding a to-do, completing the to-do, removing the to-do
- 43:00 Input string, you can do whatever you want with that input
- 52:00 You don't care about the event…
- 55:00 You know, we want to avoid chaining as much as possible…
- 57:00 Guards and actions look exactly the same
- 1:01:00 Sue asked do you have a webinar from 6 months ago…
- 1:03:00 We've also got in there a cheat sheet
- 1:06:00 I need to add some docs for that but yeah spawn…
- 1:11:00 In queue actions or on queue, depends how you pronounce it

## Transcript
[0:00] Hello friends. We are the Stately team and this is our very special XState version 5 webinar. So if you are looking for an introduction to XState, you are in the right place. If you are new to using V5, you're in the right place. If you want to migrate from version 4 to version 5, you are in the right place. Thank you everyone who has joined us live. Remember any point you can ask us questions if you're joining us from Twitch or from YouTube or from LinkedIn.

[0:00] If you ask questions in the comment space underneath the event, we'll be able to get them here and we'll be able to respond to them live. I'll just start off by introducing the folks that we've got here today. I'm Laura and for the purposes of today, I'm mostly tagging along. David, who are you? Hey, I'm David, the founder of Stately and creator and one of the main maintainers of XState. The other one is down here.

[0:00] As David I'm I'm the other maintainer of XState, the TS plumber of this team and hype man, David's hype man. So these are the perfect people to learn about XState from. And already we have hexameter saying, "Hello there and thank you for XState." And Cedric says hi as well. So I suppose without any further ado, David, what do you want to show us? How should you get started? Hey, all right. So let's jump right in.

[1:00] I am actually going to show you the studio first because that's going to be our starting point. What I really wants to accomplish in this webinar is teaching you the basics of state machines and statecharts and then learning the basics of the XState version 5 API. This isn't going to be a super deep dive onto absolutely every part of the version 5 API because that would take many hours and that's more suited for a half-day or a full-day workshop.

[1:00] Instead, I just wants to be able to get anyone who's watching this up and running as quickly as possible. So first of all, I'm going to introduce like just the concept of state machines and I was going to say you could skip over this. I guess in the recorded version you could skip over this if you already know what state machines are. Can't skip over now unless you have time control powers.

[2:00] But we're going to learn just the basics of what is a state machine and why do I keep talking about it? So a state machine describes a process or a flow or basically the logic of any part of your system and your application could be a system. And so for instance, I was going to do the traffic light example, but that's a little too simple. Here's what I want to do. I'm going to make a state machine that describes sort of a tour like an onboarding flow of sorts and we're going to be doing an onboarding flow for let's let's do to do MVC.

[2:00] Let's see the backbone version just for fun. So to do MVC, of course, it's an app that you could make to do's, add, remove. We're not going to be recreating the logic of to do MVC in this workshop. Instead, what I actually want to do is add an onboarding flow that guides users to learning how to make a to do. So we could say the first step would be that we want them to well, make a to do.

[3:00] And then we want them to complete that to do. And then we want them finally to delete a to do and then we want to show congrats, you've finished the onboarding tour. So that is our goal and we're going to do that for to do MVC. So let's let's actually make that and I'm going to do it visually here just to explain the concepts and then we're going to do it using XState version 5.

[3:00] So our first states, you know, you could call it the start states or whatever you want. This initial state, and we'll call this tour, this initial state is where the state machine always starts because you do need to start somewhere. And so it's indicated by this circle and arrow over here that points to that starting state. And these are states. So states in a state machine represents a status or mode of the behavior of, you know, that part of the system.

[4:00] So you could only be in one state at a time. Yeah, so you for example, you can't be asleep and awake. Those are two different finite states. All right. So just like we saw in our tour, when the user creates a to do, so let's call this to do {dot} added, then, you know, we're in the to do added or you could call this like the, you know, first step complete or something like that.

[4:00] But yeah, let's just call this to do added. And then we could say when we to do {dot} updated, let's just assume it's completed for now. So to do completed and I'll show you why in a minute. And then to do {dot} removed, we will have to do removed. And so once all of those steps are completed, we will end up in our final states. And so if we take a look at this flow, this describes a pretty simple flow and we go from start and then when a to do is added and then updated and then removed, then the user has completed that flow.

[5:00] So again, it's pretty simple. We're not going to be going too deep into everything and this is something where we actually have to add a guard, but we'll do that later.

[6:00] So I want to show you how we could actually do this in code using XState V5. So I'm going to go ahead and switch my screen and by the way, if there's any questions, feel free to like us Laura, you could re- relay them. I will make sure I jump in if we have any questions. So far it's just a lot of folks here are very happy with XState and I'm glad that you worked on it.

[6:00] And yeah, saying thank you and saying "it's easy to believe in the mission." So Mateus said, "thank you for believing in our mission." And Scott said, "it's easy to believe when it's so well written and solves so many developer problems." And Martin says, "thank you for making that mission a success." Absolutely. All right, I have way too many windows open. If you saw my side of the screen, you would you'd be freaking out right now.

[6:00] Well, just while you're doing that, I'll remind anyone who's just joined us that if you have any questions you want to ask, please just add a comment in YouTube or on Twitch or on LinkedIn and we'll be able to grab that and we should be able to answer your question live, hopefully. All right. So is this font big enough or should I make it a little bit bigger? Let's just bump it up to 28.

[7:00] I've got it deliberately smaller your my window smaller so that I can envisage what it would look like on a smaller device. Awesome. All right, so let's actually jump into talking about XState itself. We're going to be working off a of a vanilla JS to do MVC adaptation. It was originally created by Mark Rabanski of Frontend Masters and I actually did a bunch of XState workshops at Frontend Masters and hopefully I'll be able to do one for version 5 over there, but we also aim to provide you a lot of free material, too.

[7:00] All right, so let's get running. The first thing to do is to install XState itself. You could use npm, yarn, PNPM and it's just PNPM or npm I can use PNPM these days. Install XState. Course, you could npm install XState, yarn add XState, but it's all the same. The latest version of XState is on version 5. And also XState has zero dependencies. So now let's actually create a state machine. So we're going to import from XState create machine.

[8:00] That is, of course, how you create a machine. So the machine is going to be you could consider it the blueprints or the brains of how like how some logic is supposed to work. So if you're used to Redux or Zustand or libraries like that, you could think of this as the logic behind how your store changes when events come into it. So this is sorry, but no thanks, Copilot. That's the wrong tour machine.

[8:00] So let's actually create a machine that represents the tour that we created using the Stately tools.

[9:00] So let's give it a nice ID and this is just going to make it a little bit easier to visualize and we specify our initial state, which is going to be start. So states, we have start and then let's let's add the rest of the states, too. So we have to do added. We also have to do removed. Thanks, Copilot. And we have to do or sorry, to do completed and then we have to do removed.

[9:00] And so these are each of our states and this is how you define states. We have a top-level property called states and then you define the key of each of those states in there. And then in each of those states, you could define transitions. So we could say on and for example, this would be to do dot added. This is just a convention adding the dots, but it actually works with one of the newer XState five features which I may talk about later if someone asks about it.

[10:00] And we're going to give it a target of to do added. And similarly on to do completed or sorry, yeah, to do completed, we're going to go to the to do completed state. And on to do removed, we go to the to do remove state, and then finally, this is our final state. All right, so let's actually let's actually try out the state machine. So, I am going to I'm going to go ahead and actually copy all of this code, and I'm going to switch to the other screen.

[10:00] So, apologies for switching back and forth between screens. Let me just grab this. Sorry, it's the only way we get a zoomed in version of everyone's faces, so. Exactly. All right, so Oh, we have a question that Mateusz has answered in the comments. I'll go ahead and read that out here. What's the best way to contact you about contributing? I'm interested in helping build out XState versions for native mobile apps. XState can be just as incredibly helpful there.

[11:00] And Mateusz responded, this is like I'm being your mouthpiece, Mateusz. We are pretty responsive both on GitHub and Discord, so let's chat on any of those. You have better English, so that's pretty cool for me. Just don't be saying any comments that I don't want to read out loud. Yeah. That's tempting. All right, so just to quickly show you, we could click new machine, and then we could just import that machine.

[11:00] So, I just copy-pasted that code that we just wrote over here, and then when I click import, it's going to do the fancy auto layout, and we could see all of our states in here. Yeah, that's all I want to show, and you could click simulate and actually verify that the logic is correct. In this case, our logic is pretty simple, so you know, we know it's going to be correct. All right, so useful.

[12:00] Great way of catching errors, looking at things in a different way like that. Yes, especially when your code gets a lot more complex, then it really helps out. Okay, so let's talk about how we actually use this tour machine. And we're going to export it. So, again, I want to reiterate that this tour machine, it's not the actual actor instance. This thing is not like an instance that holds states, it's just the logic.

[12:00] You could think of it as pure in a way. It's going to purely inform an actor, this is how you should behave. So, we're exporting this tour machine. Yes. has pointed out you might want to switch to do completed with to do removed. All right, so to do added comes after removed, isn't it, originally? Let's see. So, starts, we added a to do, and then you completed that to do, and then you removed that to do.

[13:00] I think that makes sense. I guess this is just wording, isn't it? It's yeah. Is it completed on removal or completed then removal? Yeah. And this is the thing. So, you could easily like show this to non-technical people, stakeholders, and they could make that decision on their own and say, "Hey, these two things should be switched." And they could do that without having to look at the code, which is one of the main benefits of using a state machine in the first place.

[13:00] All right, so I'm going to import that to do machine. Hopefully, VS code does the right thing, which it doesn't. So, that's okay. Or sorry, it's a tour machine. There we go. Sorry, sorry for blaming you, VS code. And I adapted this example, and I'm going to share the code for this shortly after the webinar, but we have a tour component, or not a component because this is vanilla JS, but we have a tour element.

[14:00] Where is it? It is over here. There we go. And this tour component is going to show each step of the tour. All right, so how do we interact with our tour machine and actually create an actor out of it? Well, we go actually, we'll do it up here. So, we're going to create an actor, and by the way, XState version five is based heavily on the actor model. Actors are entities that could send events, they have their own internal states, and they react to events being sent to them.

[14:00] So, whenever an actor receives an event, it might it will probably just update its own internal state, but it could also do other things. It could send events to other actors, it could even spawn actors, too. So, if you think of an actor like this store, the actor model is sort of this multi-store pattern where you could have multiple stores talking to each other, which is pretty powerful, especially if you're coming from you know, some notion of a global store or a set of disjoint global stores.

[15:00] It's really useful. So, does that make every state machine is an actor, but not every actor is a state machine? So, every actor has its behavior that could be controlled by a state machine. So, the state machine is basically like the brain, the DNA you know, behind the actor. It's it's the thing that tells the actor, "Hey, when you receive this event, this is how you should react to it." And I'm going to show, if we have time, some of the other APIs where you don't have to use a state machine to signify the behavior of an actor.

[15:00] So, but we'll use a state machine for now because that's what XState's about. So, I'm going to create an actor from that tour machine. And so now, this is an instance of like this is that instance with its own internal state that could receive events and do other effects. So, I could just as easily, you know, make a bunch of different actors. And so these are all independent entities that could send events.

[16:00] But we're just going to create one for now. And the second thing I'm going to do is I am going to subscribe to that actor. And I'm actually going to do that at the bottom just to make sure that everything is defined. And so I'm going to say tour actor dot subscribe, and then we get a snapshot over here. And this snapshot is a representation of the actor's internal state. And so for state machines, well, for state machines, we have a value, and that value represents the state, the finite state value.

[16:00] So, const value equals snapshot dot value. And that value could be in our case, it could be start, to do added, to do completed, or to do removed. And so we're just going to put this directly on the app or on the to do element because we're working with vanilla JS. In the future, by the way, we are going to have workshops where we are working with React or View or whatever other framework that you might request.

[17:00] All right, so let's go back down here, and I'm going to say app dot dollar sign dot tour dot inner HTML. Again, it's probably best for you to use an actual framework instead of doing things manually like this, but for explanation purposes, I'm going to do it right here. And basically, whenever the tour actor updates and emits a snapshot, we're going to be doing this effect. And so now, I can start the tour actor.

[17:00] So, tour actor dot start. And it's not really going to do anything right now. Obviously, you can't see anything over there. I might need to reload if it still works. Ah, you know what? Maybe I'm not running it. There we go. That'll do it. Yeah. Cool, so now we have the start event. Okay, so how do we actually interact with this actor and get it to change its state? Well, you could send tour actor dot send, and you could send the events that we defined here.

[18:00] So, in this case, we have to do dot added. And the send method takes an event object. So, type to do dot added. And now you could see, we're in the to do added state. So, we successfully transitioned from one state to the other. So, what I'm going to do is I'm in order to make this actually useful, I'm actually going to send this actor to our custom store. And of course, this is going to be implementation specific just depending on how you structured your app.

[19:00] We're doing this in vanilla TypeScript. Well, I guess TypeScript's not vanilla, but anyway, we're doing this in vanilla JavaScript {slash} TypeScript to show you that you can really do this anywhere. XState is not tied to a specific framework. So, if we look in the store, I'm actually passing the actor down so that we could actually hook into some of the methods on this on this custom class. So, for example, in the add method, I could say this dot actor dot send type to do dot added.

[19:00] So now, since that's connected there, when I add a to do, so add a to do, you'll see that the state changes to do dot added. I'll I'll pause there for questions and what. Right. Hexen meter asks, are there any guide snippets on how to integrate XState with TanStack query, React query? It's our go-to lib for handling XHR in our apps. Yeah, so that is a post that I've been meaning to write for a while.

[20:00] It's not complicated, especially given the building blocks that we provide to you in XState version 5. And Mateusz could probably explain a little bit more, but we're using actually tRPC, which does use React query, I believe, with XState. And the simple answer is to use the clients directly. The client is simple. You could make your gets, posts, whatever calls, or I guess they're called mutations and queries. And you could use that directly within XState.

[20:00] And so, if you want to actually have that as a managed actor, you could just wrap it in from promise. And then that's it. So, it's probably going to be a very short blog post, but yeah, that's how you would do it. This is just a reminder to anyone who's watching. If you've just joined us, you can always watch the stream back from the beginning later on. It'll be available on YouTube and on LinkedIn.

[21:00] And if you have any questions, you can ask us live. Just go to the comments in YouTube or LinkedIn or Twitch, and we'll be able to respond to you there. Awesome. All right, so let's add a few more things. So, to do added, we know that our next state is going to be to do completed. So, we want the user to actually complete a to do. And so, that is actually done not in Oh, yeah.

[21:00] So, it's done in toggle over here. So, here's something where it gets a little bit more into the we are not into the weeds, but we're you know, we're going just away from a simple state machine, and we're doing things that are actually fun. So, I'm going to send to do {dot} updated. Now, this is all fine. This is actually probably going to work as is. So, you know, when I add a to do and then I update it just make sure that aha, you know what?

[22:00] I'm going to change this to to do updated, and you're going to see why in a minute. Let's delete these. Now, when we update that to do, you're going to see it goes to do {dot} completed. But, there's there is a problem. Like, let's say that we have, you know, some other to do's. Reload this. Yeah, so let's say that we added a to do, and then we uncompleted to do, it's still going to say to do {dot} completed.

[22:00] So, we actually need to add a condition to this transition, which would make it a guarded transition. And so, here's how we do that. Our events objects can take payloads. So, for instance, we could pass in the to do as payload directly to this events object. And that's going to be present on the events, too. Now, transitions can have guards. And so, it's just with the guard property. In version 4, it was called cond, which was a little bit weird, because you're describing a guard.

[23:00] And the guard has a condition. It's not the condition. But yeah, so we could de-structure events. And this is also new in version 5, too. Instead of having multiple arguments and trying to remember the order of them, it's all just under the same single argument. You can pass params if you want to. But, and that's going to be in the second argument, but all of the properties that you expect from XState itself are going to be in that first argument.

[23:00] So, we're going to return events {dot} to do and let's see how this is structured. Oh, yeah, it's just a completed boolean. So, {dot} completed. And it's not strongly typed yet, but we will fix that in a minute. Okay, so now when I add a to do I'm in to do added. When I complete a to do, it's going to go to do completed. So, just for sanity, if I reload if I add a to do and I uncomplete this one, you're going to see it didn't change because we didn't receive a completed to do.

[24:00] But now when we do it's on to do {dot} completed. All right, so one more thing. We need to actually detect when a to do is removed. So, I'm going to go to remove. And then we could say thanks, Copilot. This {dot} actor {dot} send this event object, which is type to do {dot} removed. Okay, so now if all works well when we add a to do it takes us to do {dot} to do added.

[24:00] If we complete that to do, takes us to do completed. And if we remove the to do, it takes us to do removed. And you know, we could show some custom messages that show that it you know, that it was removed. So, I'll pause there for or that you've completed the tour. That's what I meant to say. Pause there for questions. Anyone has any questions, you can ask us. LinkedIn, YouTube Twitch.

[25:00] I think so far it's people just quietly listening. I can tell that they're nodding their heads at the screen. We got 35 of you just coming in from YouTube alone right now, so hello. Yeah, that's awesome. All right, so because we are working in type set TypeScript, I want to make this a little bit type safe. So, to do that, we are going to add types over here. And this is also a change from XState version 4, because we really don't want you to add like a bunch of generics over here.

[25:00] I have no idea what VS Code's adding, but you get the idea. We don't want to in fact, if you look at this, which I don't recommend, there are a ton of generic parameters. The main idea is that you should not be able to see that. Those are only for Mateusz's eyes. Not even for me. I'm not allowed to see them. So, don't don't try to add anything there. But yeah, let's type context.

[26:00] Or sorry, not context, but the events real quick. Just because we don't have context quite yet over here. So, our events I'm just going to do this syntax blank as and then actually Copilot is going to be really good at filling these in for us. So, we have to do added. We have to do updated with the to do being a to do, which it doesn't know what a to do is.

[26:00] So, I'm just going to say to do is something with com- pleted boolean. And to do removed, we could give it an ID or we could remove that. And so now when you provide the types for these events, which are just a discriminated union, now we could have type completion. So, we could say tour actor {dot} send and then type. Now we have all three of our events over here, which is pretty nice.

[27:00] So, that is how you strongly type events. All right, so the other thing I quickly want to talk about is how you do context. We don't have anything contextual over here, but I just want to show just a pretty trivial example. You add context over here, and context, by the way, is just extra data that you might have in your to do machine. Again, if you're coming from something like Redux or Zustand, this is where all of that state data lives.

[27:00] So, your state machine defines what happens when an event is received in a certain state, and one of the things that could happen is that you could update this external data context. We're just going to call it context. For example, if our count is zero, then we could say that whenever we add a to do, we're going to have an action and we're going to update that count. And that count is going to be context {dot} counts plus one.

[28:00] And so, this is how you update that context. It is type safe, so it is inferring that type from context. And that way we could be sure that we're not accidentally providing something that we're not supposed to over there. And it is dynamic, but if you do need to give it a simple value, you could just do that as well. And this will also partially update context. So, if you had other properties then it's going to just assign to this object with only that property.

[29:00] So, it's pretty handy. But yeah, we're not going to be dealing with context too much in this example, because we're just describing a simple flow. Okay, so another thing that I want to talk about was actually actually, this is a pretty fun, and it sort of shows the magic of state machines, is that something that's actually pretty useful when you're creating a state machine, is creating useful descriptions. And we're going to use the description property to actually add some text and display to the user, just so you could see it.

[29:00] Again, a little bit contrived, but I just want to show you that this is an important feature, especially if you're trying to explain a flow to someone who's non-technical. So, let's say that this says, let's get started. Added to do first. Even if you're trying to share a flow with someone else you're working with on the dev team, sometimes people name things in a different way or have different approaches. It's still handy for that, too.

[30:00] Exactly. So, now when to do is added, you could say, great, now let's complete that to do, and we could add another description. Let's give it a different adjective, wonderful. Now let's remove that to do, and then give it another description. I'll use splendid. It's trying to be too smart. Yeah, you have completed the tour. All right. And so with this is getting in a little bit into the details of how state machines work, but a state machine is a hierarchical graph of state nodes, the combination of which comprise the entire state machine.

[30:00] You don't need to know all that. All you need to know is that it is a data structure, and that data structure is used to determine what happens next when you receive an event. So, just to show you, we could do something fancy like const description node equals snapshot.nodes. And again, this is just for fun, so don't you don't necessarily need to do this in real life. Node.description. So, basically, we're going to find one of those state nodes that has a description, and then we're going to set the inner HTML to either the description the state node with a description or just the value.

[31:00] So, now you see that it says, let's get started. Added to do first. So, then we type our to do. Okay. Now it says, great, now let's complete that to do. Nice. Great. Wonderful. Now let's remove that to do. Splendid. You have completed the tour. And so that's how you could use a state machine to make a tour. Okay. Fabulous. We've got a quick question from Ibrahim here. When a specific context from my state machine changes, can I React based on that change?

[32:00] Really great question. Okay. So, yeah, yeah, let's let's actually do that. Let's say that hm Okay, yeah, good question. Okay, let's say that we want to do something over here. This to do is push, and then this.actor.send to do added, and we're going to add num of to dos this.todos.length. So, we're going to just add that to the event properties to do. We definitely exists, but we haven't strongly typed this store cuz I just copy-pasted it half an hour ago.

[33:00] Okay, so the way to do that is by using what's called an eventless transition. So, and again, this might be a little bit contrived, but I in this state, the to do remove state, I'm going to make a expert state. You you'll see why in a minute. Description Wow, you are a to do expert. So, and we're going to transition to the state basically, whenever the context or sorry, when whenever a transition is true automatically.

[33:00] In fact, we're going to actually, we're going to use the count. So, now this might not be a as contrived of an example as we may think. So, when you've reached this final state or sorry, not final state, but the to do remove state, and you keep adding to dos, we want to automatically transition you to the expert state, you know, once that count reaches a certain value. So, on, and this is going to be to do.done to do.added.

[34:00] And by the way, you could see here these stars. These let you actually do partial event descriptors, and so that's why the dot convention is there. It's a little bit more advanced, but just showing you that's a feature. Okay, so whenever we add a to do, we're not actually going to transition any states, we are going to just make an assign action, and we're going to update the counts of to dos.

[34:00] So now let's say that whenever you add 10 to dos you want to transition to expert automatically, but this might not be directly on an event. So, you know, it could be a variety of events or just external things that happen. So, we're going to make an always transition, and it's called always because we're always going to transition when the guard evaluates to true. So, when, for example, context.count is greater than or equal to 10 then we're going to go to expert.

[35:00] Let's see if this works. So, we're going to add to do first. Okay, we're going to complete that to do. Going to remove the to do. We've completed the tour. So, now let's make a bunch. I don't know why I chose 10. I'm sorry. Oh. Let's see, what am I doing wrong? Oh, oh, haha. This thing auto-completed to XState 4 syntax. That is embarrassing. So, that's the one of the main things you have to watch out when migrating from V4 to V5 is the co-pilot getting in your way.

[36:00] Yep.

[36:00] Cool. Let's do that. And then Wow, you are a to do expert. Yay. There we go. So, it automatically transitioned based on that change. Fabulous. We have a question from our friend Mark. Hi, Mark. With V5 finally released, what's the next major focus for XState? In short, tooling. We want to bring the tooling up to date. We do have a bunch of like wish list items for XState V5, but we got basically the prioritized ones out door.

[36:00] Mateusz right now is working on basically getting the machine extractor up to speed so that we could get all of our fancy tooling in place, especially for bidirectional editing of XState V5 machines. I don't know if you want to talk more to that, Mateusz. Yeah, I'm I'm planning out the work for that, and for like a completely revamp of the VS code extension and everything that comes with it. So, we are rethinking the features that we might want to deliver there in stages, of course.

[37:00] But yeah, the V5 support is like the first one that we need to get out of the door, and then we'll continue just improving that with more static analysis-based goodness, and improved the to deliver like improved in the IDE experience, more integrated with our system as a whole, and like with the with the studio. Yep. All right. So, one of the last things I wanted to show you was actually the usage of other types of actors because like I mentioned when I made the XState V5 announcement, the main goal of XState V5 is to have this unified actor model way of working.

[38:00] So, state machines are just one of the types of what we call actor logic that an actor can have, but of course, you could represent your actors as promises, observables, functions, callbacks, and whatever else you want.

[38:00] So, just to demonstrate that, I'm going to make a let's call it const fetch logic. I don't know. Naming things is hard. And we're going to import from promise from XState. And so from promise is going to take, just as you expect, a function that returns a promise. So, async. And then we're going to, you know, wait for some logic. I have no idea what this is, but we're going to try it out just in the spirit of experimenting with stuff.

[38:00] Let's see what that is. And so this, just like you would create a machine like const other logic equals create machine, don't worry about like these names being different. All of the other logic that's not a machine is from whatever. You could think of this as create a machine from a promise. But yeah, we could use this with exactly the same actor creation tools and interfaces that XState provides to you. So, const fetch actor equals create actor with the fetch logic.

[39:00] And then we could subscribe just like normal. So, fetch actor.subscribe, and I am really curious what this returns with. So, I'm just going to say app. dots tour.innerHTML equals snapshot. and this is actually going to be the output of it. So, this might be like an object, we'll see. Actually, it probably will, so JSON.stringify snapshot.output. And then, yeah, that's pretty much it. And then, we are going to start the fetch actor.

[40:00] Again, I have no idea what this is going to end up with. Oh my gosh. All right, cool. So, now we know that our fetch works. I I still have no idea what this is, but Wow. That's that's pretty cool. That's a lot of stuff. Yeah, yeah. But, it shows you that, you know, we could use that logic. And also, with state machines, you could actually compose that logic, too. So, if I take this fetch logic, and bring it over here, we're just going to import from promise from XState.

[40:00] We could invoke that logic. So, let's say that we're on expert, I could invoke and the source of this invocation is going to be that fetch logic, promise. And then, on done, we are going to just target, just got stuff.

[41:00] Naming things is hard, so got stuff. Description, I got a bunch of to-do's. Okay. So, now if we go back and we just redo this, and Oh, we have to complete the to-do, we have to remove the to-do. You have completed the tour. Okay, so I actually want this to be on the other state. And so, this is a cool thing about state machines, too, is that all of this becomes pretty modular.

[41:00] So, you know, you could just move things around and that becomes more clear when you work. Oh, wow. It said I got a bunch of to-do's, it loaded pretty fast. And, yeah. So, it invoked a promise and you could actually do things with that output. So, actions, we could assign and we're going to have the event. And so, the output is going to be, events.output. And in this case, it's lane because it's coming with an array.

[42:00] So, actually, this might automatically trigger the expert transition. This is all impromptu, by the way, so let's see what happens. Great, let's complete the to-do. Oops, it's not completing. Remove the to-do. And then, I got a bunch of to-do's. Did I reload? Oh, oh, because I'm doing bets. Okay. So, again, adding a to-do, completing the to-do, removing the to-do. And then, it took me to wow, you're a to-do expert immediately because it fetched a bunch of to-do's in this really really fast promise.

[42:00] Nice. I OPM asks, is there compatibility of XState version 5 with XState inspect latest version?

[43:00] And I Matías has answered this to some degree in the comments, but David, I thought you'd like to speak to it. Yeah, and actually, let me just go to the other, screen. The short answer is, no, at least not yet with, you know, with XState inspect. However, we are working on Stately AI inspect package. And, this is actually going to be a little bit different and there's a reason why it's Stately AI inspect and not XState inspect.

[43:00] The API, first of all, is a little bit different from inspection, where instead of setting dev tools to true, you are going to give it an actual physical inspector. So, from Stately AI inspect, and if you really wanted to, you could you could already install this. It's version 0.0.9 or something. You're going to create a browser inspector, you pass it into the second argument over here. In fact, you could actually pass console.log over here and you get what's called inspection events.

[44:00] And there's three types of inspection events. There's the, actor event, which tells you this actor was created. There's the events event, confusing, but that tells you this actor sends an event to this other actor. And then, there's the snapshot events, which tells you this actor has basically changed its internal state due to an event. So, it's actually a little bit more advanced than, than the traditional dev tools that you saw and used in XState version 4.

[44:00] This is going to create a browser inspector just like XState inspect did. And, we're actually going to release something soon, where you're going to be able to visualize the state machine and also the sequence diagram of the actors communicating with each other. But, one huge difference and the reason why it's Stately AI inspect is because we're going to have an API that lets you basically inspect anything, even if it's not XState.

[44:00] And you do this by calling methods that are agnostic to whichever library you're using. It's just going to proxy those and, just send them off. Yeah. So, for example, you could send those actors and say, "Hey, this actor was created with this initial, snapshot or this events, the type hello events was sent from some actor to another actor or this actor changed states and now it is some context." Fabulous. Going back to what we were looking at earlier, Gregor asks, "what's the best way to type the inputs of a from promise actor?" Okay, I could show that real quick.

[45:00] Let me just go back to my window. And go back to the tour machine. All right, so the best way to type the inputs of that sequence actor, or sorry, the I was reading another comments, the fetch logic actor. This is actually a really good, really good question because we introduced a new API to make typing of actors, actions, and, guards simpler. And it is a progressive API, so you don't need to change what you were doing before.

[46:00] You could still use create machine as normal, but if you want to extra typings, you could set up the implementations. And so, that's where we get the setup API. So, the only difference between create machine and setup is that you would set up some stuff first and then create machine. So, it's not changed, you don't have to worry about anything, because it's going to create the machine all the same. And I'm just going to move the types up there.

[46:00] And, so, first of all, the input. So, I wonder if I could alert over here or something, but, you would have input over here and let me just double check. The I don't know if I should use guard parameters or just I'm going to do the natural you can, yeah, you can just annotate it here. So, you have say input and yeah, annotation goes here. Yep, that feels the most natural. So, input string, you can do whatever you want with that input.

[47:00] Now, you can hover over the from promise there and, it should show you that like it got inferred. So, the return that the first type inferred like type argument is any because like you just return some random JSON. It's out it's the output, yeah, but the input, the second one got inferred as a string there. Yeah, so if I say that this is an array of, an any's. An array of any's, then we could see that, yeah, it does this funky thing and then the input is a string.

[47:00] Okay, so now in setup, I could specify my actors. So, one of my actors could be that fetch logic. And all I have to do is pass it in like that. So, now if I go to my invocation, it's going to, now error because you're providing an inline actor, but if I make that a string and, it's still yelling at me for some reason. Da da da not sure why. It's okay.

[48:00] You forgot maybe because you forgot to pass the input. Like it's required. Oh, yes, yes. And, yeah, if I just read a little bit, it would have been clear. Yeah, so actually, I'm going to I'm going to do this. Just to show you the typing, we're not actually going to run it, but if I type source and then I oh, go over here, it's going to auto complete or provide intellisense for that name and then I can provide input and let's say I provide a number.

[48:00] It's not going to like that, but if I provide a string, it's going to be happy all of a sudden because it knows that the input of this object, or sorry, of this actor logic should be a string. And so, you could do the same for, guards and actions. So, let's take this guard over here and let's call this, well, let's not call it anything yet because I want to add it.

[49:00] So, guards, to-do is completed. And we're just going to pass that in over here. Oh, we do have to assert the events, but that's okay. So, event.type is not equal to, to-do update, then return true. Or sorry, return false. And then we're going to return the event.to-do is completed. There are ways around this, I'm just being lazy for now. But, if we go back to the guard, you could see that if we type string here, we could auto complete that to do is completed.

[49:00] Very nice. Now, slightly tangential, but a good question to send from Cedric here. With the new magic button to generate a React app, now this is in state Studio, is there a way to add service or actor-like fetch logic? I'm not sure that's possible today. Add service, I'm not sure it's possible today. It will be. It will be very soon. And so, first of all, I want to show people what Cedric is talking about.

[50:00] So, let me just go back to here. So, we have our tour to do added, to do completed, to do removed. Going to end this simulation and I'm actually going to add a description, too. So, I'm going to say that this is an onboarding tour for a to do MVC app guiding a user through the basic functionality. Just because it's good to add descriptions there. Okay. So, now if we click code, and click generate React app, this is actually going to be very quick.

[50:00] It's going to generate this React app and it's very basic. It's just going through each of the events, adding those as buttons, and in the future we're going to have more functionality where you could actually add in parameters. So, you could have form elements, basically. If I click in the hands app, this might have a prettier view of this, but essentially, it generates a very useful prototype React app that you could directly open in CodeSandbox and play around with.

[51:00] In the future, we might support vanilla or other types of frameworks, too. We do have supports for Vue, for Svelte, for solid, I believe. Mateusz, am I missing any? Yeah, we have solid, React, Vue, and Svelte, which solid is not yet released for V5, actually, so we don't fully have that now. Okay. But, yeah, it will be soon. While this is loading, any other questions?

[52:00] Yeah, we have a few. I'm just trying to get a good order on them. Well, let's go for this one. So, Ragnar asks, "what are the ways around the event having all possible types, except for guarding it with an if statement?" Oh, okay. So, while that's loading, I'm going to basically show you the yeah, so this is actually a big new pattern and we actually think it's a better pattern to do because let's say that you have this guard over here.

[52:00] This guard is dependent on the event and you know, we could assume that it is a you know, it is a to do updated event, but TypeScript is not smart enough to know all of the ways that this guard can be used. It can't see into the future. That's what TypeGen was for in V4, but you honestly shouldn't rely on TypeGen in V5 too much just because there are alternative patterns. So, we could do this instead.

[52:00] First of all, I'm going to make a formal to do type. And so, we could say interface to do is completed boolean. And so, now here's what I'm going to do. I don't want to care about the event, actually, and this is a pattern that you should try to internalize, too. Instead, I want to pass it in as a parameter, so that we're sort of doing inversion of control. The guard is telling you this is what I expect.

[53:00] So, our params can be let's just make this a to do. And so, now we have a bunch of stuff over here. We know no we no longer need this because we don't care about the events anymore. We just know or we expect whoever is calling this guard should provide us to do as a parameter. So, let's see how to do that. Instead of passing a string over here, the guard type is to do is completed and it expects parameters, too.

[53:00] So, params and we have the events over here, which already is strongly typed. So, we could just say to do is events.to do and TypeScript is perfectly happy. So, now you don't care about the event, you get that to do from params, which is strongly typed, and you could specify the params dynamically here, which is also strongly typed. So, I'm really glad you asked that question because this is a pattern that we do want to encourage moving forward.

[54:00] It makes these a lot more flexible. So, now you could use this guard in any machine. It doesn't matter. It's not dependent on the context or the event. Nice. Should we go and check up on where the studio is at with generating that enhanced UI? Oh, sure. Yeah, it actually completed a while ago, but I'll show you right here. Yeah, so when you click enhance after a minute or so, it's going to give you three versions of that thing and it's it might add some extra UI there.

[55:00] So, add a to do, you have add to do, complete the to do, remove the to do. colors.

[55:00] Very good. Yeah, yeah, it gets pretty fancy with the colors. I'm not even sure what this is going to look like. Yep, so same sort of thing. It gives you a sort of prettier flow. And this is all Ooh, I really like this one. It even has some animation. Nice. Now, you're ready to use the to do MVC app like a pro. So, really good for prototyping. I have a lot of fun with this feature.

[55:00] One quick question on my own behalf. Where are we able to find this code that you've been demoing to us today? Will we be able to put it up somewhere where we can grab it? Yes, I'm going to put it up as soon as I fix all the original type issues in the in the original code. I'll just clean it up a little bit, add a read me, but yeah, by the end of today, I aim to have this up.

[56:00] Here we've got a question from Nick. Can the setup function be chained at all into another setup function or we need to spread shared events actions into just one setup function? So, Mateusz said no chaining right now and that right now it really depends on what we want to do. You know, we want to avoid chaining as much as possible, but for some things, you know, it might make sense to chain, especially if you want to extend setup.

[56:00] Really, we're just waiting for you know, just for people to use it a lot and say, "Hey, it would be really nice if you could do this, this, and that for these use cases." Because we like adding things based on real use cases, not based on hypotheticals. Parker asks, "isn't there a dot provide or some way to extend?" sure. So, you could provide, but that's not going to allow you to add new actions or actors or things like that.

[56:00] You do need to declare those up front.

[57:00] So, what Parker's talking about is we have this tour actor and actually, sorry, we have the tour machine right over here and let's say, looking back at the tour machine, that we actually want to switch out this to do is completed logic. So, what we could do is we could say tour machine.provide and we could provide it different implementations. So, we could say guards to do is completed and then we could just, for example, always default to false or something like that.

[57:00] You could have different conditions there. But, the types must be the same. And so, that's how you could override them. This is extremely useful for testing, too. Now, I don't want to go so much over old ground right now, but let's just jump to this in case you think it's worth responding to. It's Chris asks, "is there a similar pattern for type checking actions or is narrowing the current best practice?" So, as Mateusz said, David showcased guards, but the same principle applies for actions.

[58:00] Yeah, so again, you could provide params and you could say like message string. And then yeah. The the exact same pattern applies. We try to be as consistent as possible with the API to reduce the API surface area. Guards and actions look exactly the same. So, we have those params as a second argument and you could decouple them in exactly the same way. So, I could say on entry here, I want to greet and my params I could actually, I'm just going to do a normal object over here.

[58:00] My message is going to be hello world. And there we go. Fabulous. Ragnar asks, "I know this is kind of a follow-up from my Discord question, but is there no way to serialize the actions that are run from invoked promises while keeping it type safe?" serialize the actions that are again, you would use the dynamic parameter pattern. So, again, going with that inversion of control, you're going to say these actions expect these parameters instead of these actions expect this specific type of output from the events.

[59:00] Great. And Parker says, "the narrowing being shown seems very similar to input. Would guards and actions benefit the same naming convention? Like parameters and input is kind of the same thing in a way. Like those are synonymous. For actions and guards like we picked params just because like it's not an ongoing like actions and guards don't represent like ongoing processes or anything like that. Whereas with actors you also have the notion of output.

[59:00] So like having the naming like symmetry between input and output made sense there. Exactly. Guards actions don't have input output. They just have one thing that goes in. Which is params. Devon says love the inversion of control on guards. I feel like that's huge for guards composition. Yeah and going to quickly mention too that we do have higher one of the biggest new features of XState 5 is higher level guards or higher order guards, whatever you want to call them, which you have and or and not.

[1:00:00] So you could actually combine these guards and say for instance guard and oops and then we could have that predicate there. So to do is completed and we could have something else like false over here. But yeah these specifically work with those named guards too as well as inline guards.

[1:01:00] Nice. So just as we're getting just past the hour mark I thought it would be worth chatting a little bit about migration and we have a good question here from Sue. Sorry Sue I was going to get to it. You're further up. Here we go. And Sue asked do you have a webinar from 6 months ago migrating to V5 beta. Do you know if all the info in that is still valid?

[1:01:00] So I think this is a good point to discuss what has changed since the beta or like in the last 6 months of the beta. I'll I'll have to remember but most of the things are still going to hold exactly the same. I would say that yeah in fact everything should still hold. I just want to show here that if you go to stately.ai/docs/migration our URLS are so simple that you could just type them naturally.

[1:01:00] We have a lengthy but simple and straightforward migration guide from XState 4 to V5. You will honestly only need to do a small fraction of these things but we have detailed like just the difference between the V4 conventions versus the new V5 APIs. With regard to the old migration video I would say most of it actually pretty much all of it still applies. You still have from promise you still have guards instead of cond.

[1:02:00] The things that were added and are new are things like params. We changed the callback actor a little bit but honestly most of the things are going to be exactly the same. If not everything. But we will do an updated webinar for that soon. Totally. That's a great idea. By by the way now in the docs if you go to stately.ai/docs or /docs/XState all of our docs will now default to version 5 but the information for version 4 is still there if you choose version 4 from the drop down in the top bar.

[1:03:00] And we've also got in there a cheat sheet.

[1:03:00] So if you go to stately.ai/docs/cheatsheet you'll get a great V5 cheat sheet with a lot of what we've been talking about today. Yep. So if you go to cheat sheet should be over here. There we go. Very nice. We have we did have another question. Where has it gone? There we go. So Ragnar asks given the new param/input workflow would you recommend separating guard/actions from the machine definitions and unit test independently?

[1:03:00] I believe you could do that. What what do you think Mateusz? Yeah like that's that's like up to the project's testing practices and all but this pattern kind of allows that. So so it's much more doable to unit test some utilities and stuff like that for example. If you if you follow this pattern because you can like externalize simpler functions instead of for example our you know assign actions and stuff and like figure out how to unit test that.

[1:04:00] I will post in the comments in a second like comparison of both approaches sort of. But so far StreamYard rejected my message so I need to figure this out. It has a link or something in it. But yes yeah so that totally enables that. Fantastic. Is there anything else that we needed to cover? Folks this is a good point to remind you if you have any questions that you want to ask David or Mateusz.

[1:04:00] You know only the people who are creating and maintaining XState. You can get answers direct from them if you ask us on YouTube on Twitch or on LinkedIn and you can always find us on our Discord. I'm just trying to find the URL for that. There we go. discord.stately.ai and it has been known that we are very active in there. So if you ask a question in the help channel there you will be sure to get an answer.

[1:05:00] Ragnar can you showcase some UK use cases for higher order logic? But show some templates first since you've got them there. Yeah yeah so first I just want to quickly talk about the templates. If you wanted to get started quickly first of all the API you just import create machine and create actor and that hopefully this webinar showed that's really all you need. But if you do want things at the click of a button or at the click of the link then you could just go to any one of our templates on CodeSandbox or StackBlitz for XState and React or XState and Vue.

[1:05:00] But yeah we do have examples of guards over here. So if you go to the higher level guard section you could show for example and is valid is authorized. If you weren't using inline guards before I've seen this a bunch of times in version 4 where you would have to write a weird long guard that said is valid and is authorized and you would have to manually do something like that and you no longer need to do that.

[1:06:00] You could just write this.

[1:06:00] I'm just copying I'm just copying Mateusz's post to see if it will work. Oh that's not right. Come on. There we go. Hopefully that will go out. That look good to you Mateusz? Yeah. Yep. Fashion chips that is funny as in fish and chips I'm assuming asks do you read Twitch chat? Yes we do. Ragnar says can you explain the difference between the param spawn function and the spawn child function exported from state?

[1:06:00] Yeah so actually let's go to spawn. Okay. So we actually introduced a new function called spawn child or actually it's an action creator and we moved spawn to inside of assign. So before it was globally imported it was magical. Don't use it. So cuz now everything is more type safe when you import it directly from assign over here. You would use assign to spawn or you would use spawn in assign to spawn an actor that you need to save to context.

[1:07:00] If you don't need to save it to context then you're fine just assigning it to the snapshot.children with an ID then you use spawn child and hopefully I have Okay. I need to add some docs for that but yeah spawn child is very new. But yeah so that's the difference between the two. It's it's also worth mentioning that when you are using spawn within the assign when that actor stops or like on its own or either or either if you just stop it on your own I mean if you stop it explicitly and if it finishes you might want to actually like remove it from the context.

[1:08:00] It won't happen automatically. So you need to just combine you know you need that symmetry. You need to start the actor at some point and then you also need to dispose it. And if you don't do that like you are risking a memory leak or something. It might not always be you know important for you if your machine is small or if like the parent machine itself is disposable. But if you manage many actors over the course of the application then it might be very important.

[1:08:00] Whereas like with spawn child we are completely in control of that. So you just like the cleanup happens automatically because it's not in the context. The context is the value that you manage so you can't really like remove it magically on your behalf. Yeah. So prefer spawn child whenever you know get the chance. And we will update these docs. So that they have more examples. Yes. There are a huge amount of docs in there.

[1:09:00] We've just found one of the examples where there's not so much. Again you can find the docs at stately.ai/docs/XState. And if there are any more questions that you have for us around these docs, if you want us provide more docs on anything specific or any more examples, let us know on our Discord and we can help you out there, but we can also then translate that through to the docs, too. It's been a lot to update.

[1:09:00] Mhm. And oh yeah, that's a nice example straight of simple machine. And a lot of these examples do also now have embedded machines from Stately Studio as well to help you visualize what that looks like, which I'm quite pleased about. With colors and everything. Mhm. Yeah. Oops. Here we go. Like that's that's an example of a simple machine. And here we go, this is an example of a complex machine. So, these are not just screenshots, these are actually machines that you could play around with.

[1:10:00] In the future, we're going to let you toggle between the read mode and simulation mode. But of course, you could just zoom into the selection like that. And take a look at everything. And these are all generated from the code examples themselves so you know that it's exactly how it all works. Right. Fabulous. So, I think 1 hour and 10 minutes is a good time to wrap it up. Folks, if you have any more questions that you want to ask us, you know that you can find us on our Discord, which is at discord.stately.ai.

[1:11:00] I know it off by heart, but I can't find the banner.

[1:11:00] There we go. And we are also on pretty much all of the social media platforms. We're at Stately AI or Stately if you want to find us on LinkedIn. And you can ask us questions there, too. And you can also follow us for the updates on when our next webinar will be, when our next live streams will be. I'm sure we'll have another office hours for you soon. Or if you subscribe to us or follow us on YouTube or on LinkedIn, you'll get notified as soon as we've got the next live event scheduled.

[1:11:00] Mhm. Oh, nice. Chris says, "one of the most underrated changes is in queue actions." Yep. In queue actions or on queue, depends how you pronounce it. It allows you to get rid of pure and choose, which we have removed from XState version 5 because now you have a more natural way of well, on queuing actions to be executed. And also, you have a type-safe way of using guards, too. So, it's sort of a combination of choose and pure, and you could even do things like put on queued actions inside of if statements, if else blocks.

[1:12:00] You could even use for loops, whatever. So, it becomes a very, very natural way of coding your actions as long as it's synchronous. You can't do async on queuing because that defeats the purpose of a state machine. We've got loads of great feedback from the stream. Hitesh Aal says, "great stream. Love the discussion here." Devan said, "appreciate all your hard work, team. You're amazing. I'm hyped for V5." and Mark says, "and our wrist is Mario will be up on Twitter later." Logic Labyrinth says, "we'll be trying this out later this week.

[1:12:00] Thanks a lot." Awesome. So, thank you so much, everyone, for joining us. Let us know what you want to hear about next. I think we have an idea that maybe we will do a webinar for XState V5 with React at some point soon. We may also look at doing it for other frameworks, but let us know what matters to you and we will make sure that we get that done. Thank you so much for joining us, everyone.

[1:13:00] We'll see you later. Goodbye. Thank you, all.
