# Webinar: State Machines and Actors with XState v5

Canonical: https://davidk.dev/talks/webinar-state-machines-and-actors-with-xstate-v5/
Video: https://www.youtube.com/watch?v=1NsSHkao-q4
Speaker: David Khourshid (@DavidKPiano), creator of XState
Type: Webinar · Event: Stately webinar/stream · Year: 2024 · Duration: 2:42:16 · Views: 7520 (as of 2026-10-19)
Topics: Actor model, XState, State machines, Event-driven architecture

## Summary
Learn how to manage and visualize application logic with state machines and actors with XState v5! In this webinar, we will be creating a real-world app where you will learn:

## Key takeaways (quoted from the transcript)
- The first part of this, it's just going to be a structured way of teaching you, the basics of XState, so the principles of the actor model, and state machines, and statecharts. (0:00)
- As a way to, manage logic and actor logic and complex state management and state machines, and things like that. (28:00)
- I like to think of a state machine, or using state machines in XState as basically like using an airplane. (36:00)
- If you're new to XState and statecharts, all this means is that you could have states that are inside of states. (56:00)
- It doesn't need to know about the feedback machine or any of these other actors, it's it doesn't even need to know about the actor, model or state machines at all. (2:14:00)
- You could also click simulate and click through these, and this will give you a better understanding of how state machines actually work. (2:37:00)

## Chapters
- 0:00 Introduction
- 14:00 Going to do the same thing over here, and so…
- 20:00 We have promise actor logic, and…
- 28:00 We send type, feedback., update…
- 53:00 We just going to show spin, spin, spin
- 1:00:00 What you could also do is assign individual context properties such…
- 1:13:00 I would just send type, feedback. reset
- 1:21:00 Let's say that we're in the form state and the close…
- 1:38:00 We see our state. context. feedback
- 1:56:00 You know, we have step one
- 2:05:00 In our prompts, we have a history state and this history…
- 2:13:00 Let's say we have a notification…
- 2:25:00 You shouldn't use it to control the state machine and say…
- 2:41:00 If you have any question, questions or comments…

## Transcript
[0:00] All right, hello everyone and welcome to another Stately XState stream. So, my name is David Khourshid, I am the founder of Stately LE and the creator of XState, and I created XState about, I want to say, eight years ago, and really. It started off as a way to express state Machins and statecharts and Javascripts. And then it evolved a little bit past that. To be a, state man management solution for managing complex app logic.

[0:00] And so we're going to get into a little bit what that means today. I am going to be sharing this on YouTube, Twitter and LinkedIn, so please, if you have any comments, then I should be able to see them here in Streamyard. And I will, answer any questions that you may have along the way. The first part of this, it's just going to be a structured way of teaching you, the basics of XState, so the principles of the actor model, and state machines, and statecharts.

[1:00] And then, I'm going to be answering questions and just, taking comments and just talking with you all. So really, this, this webinar is yours. It's however you want it to go, so if you have any questions or suggestions, then please feel free to ask me. I see a bunch of people saying hi in the chat already. All right, so I'm going to, let's just jump right in. So I am going to, go ahead and share my screen.

[1:00] And we, just like before, if you've seen the previous webinar, this is going to be the same type of B bu. We're starting a little bit, before, you know, we dive into the complete app, and this is going to be based on the feedback form. And so, if you've looked at the XState, let me just fli up the link over here, the XState GitHub page, then. Then you'll see that there are a bunch of templates and also examples in there, and I'll I'll show those a little bit later on.

[2:00] And one of those examples is a feedback form. So we're going to be starting from the beginning and working our way towards there. So you know what, let's just jump right in, uh. This is, by the way, this is a React app running in beat, but this tutorial is not, or webinar is not specific to Beat or React, or anything else really. We're just using it to teach all of the principles, so the first principle I want to teach is actually the actor model.

[2:00] Because XState version 5 emphasizes actors as the, you know, the primary unit of abstraction, just like actors in the actor model are a primary unit of computation. And so what is an actor? And I'll just put it here, by the way, if you can't see the Pwn size, you know, please let me know. I tried to make it big enough so that we could see everything. So actors? An actor is again a unit of computation that has its own internal states.

[3:00] And so actors can also send events, which is a really important concept. Or, send messages, really. But in Xay we call these events. And an actor can also, of course, receive messages, and when it receives messages, it can change its behavior based on that message. So another thing that actors can do is spawn other actors now. This right now might be a lot to take in. But, if you're familiar with state management libraries like Redux or Zustand, or, if you're coming from View, we have PiA or Angular, we have NGRX, things like that, or even in other languages.

[3:00] You might be familiar with the concept of a store, and so a store, let's just make a fake one over here. A store is something that, you know, has its own internal states. And, you know, we could send it messages. And this looks different, depending on which library you're using. But you know, this might be, in Redux. You might have like, store. dispatch, and then, you know, you would dispatch something, or you might even call some methods.

[4:00] It's like, store. add thing. But this is just a way of sending events to the store. And so, what stores don't have exactly is a way to, like, spawn other stores, but really stores are, you know, just a I guess you could call them a partial actor. So in XState, we also have these stores, but we. Have stores with superpowers, and these superpowers, like I mentioned, is you could spawn other actors.

[4:00] You could also do things like subscribe to these stores, actors. So, they're, they're really useful as a unit of abstraction. And so that's why we're going to start there today, so we're going to create actually a very, very simple store. By the way, I see there's almost a hundred people watching, so, you know, thank you all for watching. And so we are going to import from XAT, and by the way, J.

[5:00] To get started, all you have to do is MPM. Install XState. And if you're using something like Reactor View, you could install a, an adapter library like XState React or XState View. Whatever you want to use. And that should be all you need. XState has zero dependencies, so, yeah, no need to worry about dependency, hell or anything like that. So the first thing we're going to import, surprisingly to some of you, is not a state machine, but we're going to import.

[6:00] From transition, just to demonstrate what this actor model is, and so a transition function is like a reducer. If you if you come from the Redux world or similar. It's going to be, it's going to feel very, very familiar, so I'm just going to make cons. Count. Logic equals from transition. And so the first argument is going to be our, our reducer function. We try to avoid using the term reducer because it's a little bit, off-putting, and really, it is a transition function.

[6:00] You're given the states and the event, and your goal is to return the next state that follows that. So, let's just return the states just to see what happens over here. And then the second argument for from transition is just your initial state. So let's say we have count zero, so we have a simple hello world component over here. And I'm just going to make a nice big H2 tag, with count, and how do we get that count in there?

[7:00] So this is where an adapter library, comes into play. But, yeah, so I'm going to just import and this is, let's see what am I going to use, useActor ref from? XState React and I'm I'm going to show you how to do this using an adapter and also just using plain Javascripts too. So, first we make that actor, so, and we call it an actor ref, because it is a reference to that actor.

[7:00] And you could pass it around in events and things like that. But count ref equals use, actor ref counts logic, so this is your logic, this is logic that. It's basically a fancy object with a transition method where you could, instantiate an actor instance. So we could actually make many of these, so we could make another one, another one, you know, we, we, we can make many of these actors, and so that's.

[8:00] That's a distinction between an actor and an actor. Logic, so you can think of the actor logic like DNA, and then the actor as like an instance of that actor logic. All right, so now to read the value using this adapter, we could do this. Con counts equals count ref. Get the snapshot from that and then read it from the context. And then we have the counts over here, so you're going to be able to see counts zero right over here.

[8:00] But that doesn't give you the most upto-date count. If we were to do something like update that counts, so how exactly do we update the counts with? From transition? This is just your typical. You could use a switch statement or you could use an IF statement. And I'm just going to cheat and let co-pilot do this. So we pass an event object with a type and let's say that this is increment, and then we're going to return the updated state again.

[9:00] This should feel pretty familiar. So now if we have a button over here and this is an increment button onclick now, we could send that count ref in event object with type. Inc. But you're going to see that this is actually not going to work, so we're not seeing anything. And that's because we're only reading the first, you know, the first count value. So nothing is really updating and it's not going to magically update for us, and this is on purpose.

[9:00] We don't want to have too many renders, we actually want to subscribe to get the. Value that we want, or to select the value that we want. So to do this in a React adapter, we would useSelector. And then, you pass in that actor ref, and then you pass in a way to select that count. And so you could do anything in here. Right now we're just reading the counts from the states, and so now when we increment, you're going to see that goes up.

[10:00] Okay, so how do we do this then, without using a library, or, sorry, without using an adapter if you wanted to do it in vanilla JS? And I think that's really important to understand. So I'm going to sort of cheat over here and put output, which is a nice fun. Lesser known HTML elements. And so what we're going to do is we're going to just make an actor outside. So, and I'll answer, answer all the questions in a minute.

[10:00] So cons count X actor the way we create an actor is we have this create actor function from XState, and you pass the logic in there. Now. From here, you could do a couple of things. You could subscribe to that Contactor, so whenever it updates, you're going to get the latest snapshot so con. Actually, we could just do count, actor. subscribe, and then we get a snapshot of the states. And then, thank you, co-pilot.

[11:00] Uh. What we could do is just read this output and oh, it's expecting a string, whatever, we'll just trick it, um. And we could directly set the app of the inner HTML to whatever the count is. And so now, remember, we're, we're actually not using any of this at all. But now if we increment, let's reload probably won't work because we're trying to do something weird. But if we were to con console..log.

[12:00] Oh, H, I think this is because, huh, I'm not sure. H. It should show it. Maybe I'm doing something wrong, but, you know what, let's do it another way. H all right. Sorry, my mind is blinking over here. But ideally, this would just output it to the output over there. It, we're probably just fighting with React or something like that, but that's okay. Actually, let's do document body. Do Pen child, all right, forget about that.

[12:00] So, and I'll. I'll show you how that all works later, with the middle of JavaScript. But the idea, oh, okay, sorry, I know exactly why. Early in the morning for me. So we have that actually starts the actor, so count, actor., start, start, and then, yeah, this button is connected to our other actor. So we're going to get rid of this and then we're going to call count actor.. Send type Inc.

[13:00] Okay, so now this will work, so now you see that we're incrementing it using vanilla JavaScript. And so basically, this is the XState API, you create your actor logic, so I'll just write here, create actor, actor, then optionally, you subscribe to actor snapshot, updates, and finally start your actor.

[14:00] And so that before we even get into state machines, that is how you, that's basically the XState API is those four parts. So I'm going to pause here for questions. I see there's 175 of you watching, which is awesome, so, let me just pause and answer a few. See, hi David, thank you for this new webinar. Looking forward to getting more deep dive into V5 actors. And that's why we're starting with actors today.

[14:00] Does the inspector allow binding in two ways right now? So, this has to do with the Stately inspector, which we'll get into a little bit later. And it does not. I don't believe it yet. It currently supports two-way binding, but that is coming in a future update. So Jeremy asks, do states changes? Cascade? If you could, clarify that a little bit, I'd love to know what you mean. By that, let's see, counter goes.

[15:00] Bur yeah, okay. So if you have a chain of relevance and something along that chain changes, do those changes Cascade along the chain? So, I think this might have to do with, you know, just derived state and things like that. And really, that's a pattern that you should be using anyway, is derived states. So, by deriv states. I mean that, like, let's say that you have a selector like this. And instead of doing something like keeping is count over 10 or something like that, you should derive.

[15:00] That from your original state value so is counts over 10, and then this would just be like that, or actually over here, you could. You could even read it directly from the count. So you might not even useSelector over here, you could just say count is greater than 10. But, you know, just for example purposes, you could just use a selector there. Hopefully that's what you mean, but you know, I'm happy to answer any, followup, follow-up questions to that.

[16:00] Let's see, uh. C ID correct would be nice to be able to pass a possibly undefined actor to you selector, to be able to have conditional actors. I found a workaround by Mat, so Andus and thread, we'll get into that later, but long story short, you can do that already. All right, I'm coming in late, I'm thinking AI contexts as states change machines. All right, would love to hear more about that.

[16:00] Okay, so let's get back to our, you know, our actors. So, you see, we have from transition here, and this implies that there might be other things, and actually that's that's true, so transition. Functions like this, of course, are not the only way that you could express logic in XAT, so there's a few other ways. And, I'm just going to show you another one of my favorites. Here. We have con, let's call this a promise logic, and this is just going to be from promise.

[17:00] And of course, we have our ASYN, a weight function. And then you could basically do, you know anything here? So so, we could. Cons. Result equals awaits new promise. And we're just going to make a fake one over here. That resolves with done after one second, and then we could just return that result. So this is just like you would write any other promise. In fact, if you got rid of this like this, is ENT essentially just a promise.

[17:00] All we're doing is wrapping it in from promise. And why are we doing this? So that this promise log can be used as an actor, too, and it has the exact same interface and the exact same abstractions as any other actor. You would create. So I'm going to take this promise, logic, and we're. Going to do the same thing over here, and so, let's see gonna call this promise. Actually, yeah, we're gonna call this promise actor, and we're going to use our promise logic instead.

[18:00] And so now you could see that, we don't have context on the promise. Instead, we have an output because actors can finish, and when they're finished, they could have some sort of output value. So, let's just make sure that's a string. Okay? So you see that it starts with undefined and then it goes to done. You know, we could sort, pick it with that, there we go, and, yeah, we could also say that, we.

[19:00] Actually. This is going to automatically invert just, or it should. Actually it doesn't over here, but we could say, um. Promise string if you're using TypeScript, and then this should be, I think it'll infer all the way through if we just use string over here. But regardless, now you're going to see that the output is going to be typed as string or undefined. But anyway, that's how you would use promise, you know, promise actors, but yeah, so there's other ones, so there's observable actors, and there's also, event observable actors and callback actors, too.

[19:00] We might get into those a little bit later, but I think that it would be really good to start with. Actual state machines, because state machines are just another type of VOR logic.

[20:00] So, like I mentioned earlier, we're going to be creating a feedback form and just to give you an idea of what this should look like when it's done. First I'm going to just remove all of this and we have an app final, so I'm just going to show you the end result first. And then we are going to take a look at, basically, how we can make this. Okay, so this is our feedback form.

[20:00] And you can imagine building something similar to this, something like a multi-step form, or something that has many steps in its process. Whether it's in the front end or the back end, and even in the front end. Like, having something that has multiple steps and representing it as an array might not be satisfactory because you. Might want this to do different things, depending on which step you're on, or what actions the user takes, or what events happen.

[21:00] And this is actually a pretty good, minimal example, which is why we use it for the templates, in the exit repository. So this is a sample feedback form. How was your experience, good or bad? So if you click good, it says, thanks for your feedback, we could, provide more feedback. If you click bad, it takes you through a different flow, so you click bad. Now we have a form over here where, like, what can we do better?

[21:00] Show more state machines? I don't know, reduce the learning curve, which is what I'm really trying to do here. And then we could submit that and then we have thanks for your feedback. And I think you saw over here that, you know if we were to reload this, that this is going to be disabled if you know if, if we don't have valid feedback. So basically, if there's nothing there, we forgot to trim it, but that's okay, we could go ahead and do that later.

[22:00] So that is what we're going to be building. And I, I really want to start from the beginning here. So I am just going to, remove a bunch of stuff, and we're going to start from the beginning. So, see, we are going to just take this form, that's all I want, all right. So oop, sorry about that turn that. So I'm actually going to remove that and that's a false and we're going to remove that.

[22:00] And this is just to show very, very simple example of, you know, using a state machine. And had a do it. So that, you know, things don't get too scary. All right, so I'm going to delete a few more things and, yeah, we'll delete that too, okay? So, just like the other types of logic, a state machine, in fact, you know what? I'm going to open it t draw just to, just to talk about this.

[23:00] So we have, you know, of course, different typ of actors, or, sorry, different types of actor logic. We have promise actor logic, and, we also took a look at transition actor logic. Which is just like a reducer. And then we have, state machine logic, and so all of these actually do, you know different things? So, oops, okay, yeah. So these are all actors in the sense that they could receive events, and they have their own internal states.

[24:00] However, a promise actor, does not, so it does not receive events, it just starts off immediately. A promise actor also. You know, just eventually resolves with one value, and so, this, you know, it might never resolve, of course, but eventually it's going to only resolve with one value. And it can't, get spawn other actors. So, transition functions. On the other hand, these actually can, these, receive multiple events, and they, they don't resolve within value.

[24:00] They're just continuous, so I'll just put continuous. This, doesn't finish. I mean, it might in the future. And of course, this can't yet spawn other actors. And so with a state machine, you have basically it's, you, you have a lot of things. So it could receive multiple events, it can finish, it can spawn other actors. So there's, you know, basically you could see a state machine as a super set of the other types of actors, or the other types of actor logic.

[25:00] Now, of course, if you don't need all of the features of the state machine, then I really recommend you to use some of the other, you know, actor logic. Creators that are available, such as promises, transitions, observables, call backs, E.t.c. All right, I'll pause here for questions before we dive in, all right. Javier says now that everything is an actor, what would be a good criteria to either go for? Combined work of actors versus a state machine invoking actors?

[26:00] I think this is a really good question. And Javier says, I, answered this in ta draw. But still, the distinction is important. You know, basically, how, like, when would you go from a single actor to like a multi-actor system? And the the sort of copout answer is, it depends. But the analogy that I like to give is it's sort of like, being in a work environment, like, let's say that you're a manager who's technically skilled and you have.

[26:00] A big project that you want to do. You could do all the work yourself, like, there's nothing wrong with that. But that can get very complicated very quickly and it could overburden you. What you could also do is just have a team of, you know, a handful of developers and other people who are helping you out. To perform this project. Now. The problem with that is that it also introduces other complexity, too.

[26:00] Because now you actually have to sync up with them, have meetings, make sure that they're doing the right work, coordinate with them, have them coordinate with each other. And so, even though you're reducing the work burden on yourself, you're creating a new work burden. And so that there's this point where, the benefits outweigh the, the drawbacks to that, um. And the same thing with the actor model. Just like you don't want your app having, like many, like microservices, there are an appropriate amounts where you're like, okay?

[27:00] This does introduce some complexity in the message passing between all these little actors. But it is manageable compared to the alternative of having a single monolith and having that try to coordinate everything, because then you could get into things like race conditions and other things like that. So I, I' like using real world analogies. And I think that makes a lot of sense when trying to determine whether you should use a single actor or multiple actors.

[27:00] But I would say to start off with, always start with a single actor.

[28:00] Let's see, Nickas asks, do snapshots of promise actors have a state prop? Like, do they have pending done? Yeah, so I'll, I'll show that in a bit, please remind me. But snapshots do have a status property where you could see whether they're active or they're done. Yeah, let's see, Haer asks. Are XState and effects TS interchangeable there? So this is a good question, sort of common, but, they're not interchangeable. You could think of the AS, like the missing standard library for TypeScript and XState.

[28:00] As a way to, manage logic and actor logic and complex state management and state machines, and things like that. But, I like to say that effect is useful for the effectful parts of. XState, and XState is useful for the overall structure. Eric asks, can we call a collection of actors a troop? And Ellias asks, what are the optimal way of sending events to child actors and accessing their contacts? What about for a grandchild?

[29:00] That's something that we're going to talk about in a bits, too. But we're starting like here from the beginning. If like, as if you don't know XState at all, okay? So let's actually create a state machine now. State machines sound really, really scary and complicated and everything like that. But honestly, the simplest state machine is a state machine with a single state. And so I'll show you over here to create a state machine.

[29:00] I'm going to remove these. We import create machine from XState, and actually XState has a better way that we're transitioning to, which is called setup, which in. In fact, let's go ahead and start with that. So if you're usess create machine, let me show you how to, you know, transition, pun intended, from that to setup. But we, we'll start with that, so const create machine, or, sorry, const machine equals, and we'll call this feedback machine.

[30:00] Actually, machine equals, create machine. And then we put in an empty object. This empty object is the simplest state machine that you could represent. It's pretty useless, it doesn't do anything. When it receives events, it doesn't change its state or context. In fact, it only has one, basically one state. So this machine is extremely simple, but also extremely useless, so let's make it a little bit more useful. And we're not even going to get into finite states just yet, even though Co-pilot really, really wants to.

[30:00] So we are going to give it context, and this context is just, data that is not really a finite state. So just basically, non-finite data that you might want to represent in the state machine. And so the these things that could be like feedback counts, user data, E.t.c. But I, I would honestly start here. So before we even dive into finite states or anything like that, we have our context and so we have feedback.

[31:00] It's an empty string, and now we need a way to update that feedback so we could have an object with on and let's have an. Events called feedback. update, I mean, you could call this update feedback, you could do like feedback, whatever you want, but when we update feedback, we want to actually change the context. And so the way that we do that in XState is through actions, so, one of the actions could be assigned, and then we assign to feedback.

[31:00] We're going to grab the events, and let's say that we get that from events. feedback. Okay, so this is our machine and so we're saying that we're going to pass in or we're going to send it in. Event. And this event is going to have this type and it's also going to have a feedback property. And so we could use this assign action to update it. Now. Something that's really, really important to note is that in XState, this returns an object that looks like type X. Assign.

[32:00] It might have assignments, and, so it, it sort of looks like that the assign function doesn't actually do anything. So we could, we could even call this update feedback, and we could say, H, update feedback equals, and then we just pass it that assign function. So this is going to be an action object. In version six, we're going to be making this a lot simpler by the way. But just to show you how it currently is, this returns an action object that tells that state here's what you should do.

[33:00] You know, when you, like, like, when you get this feedback.. Update events. Okay, so let's actually use this now, and of course, you could do this in vanilla JavaScript. We're going to be using it in reacts just to make things a little bit easier. So I would say the easiest way to get started is with the useMachine hook. I'm going to import that from XState React, you could see here, and this useMachine hook is going to, just like useReducer or even use states.

[33:00] It returns a tuple where the first argument is a state or the current snapshot of the actor that's created by this. And then we have a convenience send function over here. Okay, so now we could actually, let's put this in the value over here, and the this is. Just for explanation purposes, and let's actually give it some default feedback, but I have no idea. Okay? So if we save this and reload, we see, I have no idea, so pretty simple.

[34:00] Now, how do we actually update this? So we, we have this onchange property that looks pretty helpful. So what we could do is we could send type and you'll see, TypeScript isn't helping us just yet, but I'll show you how we could make typescripts work for here. We send type, feedback., update, and we give the feedback that events. target. value. So now, you can see it's showing there, and actually, let's let's add a P tag and actually just show that state happening here.

[34:00] Okay, so you see, we have our two-way binding. Sort of, it's not really two-way binding, but you could see that. We're sending events in the form of feedback. update, and it's updating like you could get it from state. context. feedback. Now this, you know, this is just a really easy way to get started. So just like useReducer or use, yeah, useReducer, Redux stand, we have a way of updating the value, or, sorry, we have a way of sending events that updates the state of the actor from here.

[35:00] So, yeah, let's actually continue with this, and then I'll show you a couple of other patterns again. I will pause real quick for questions. Nikita says. X is so impressive. It looks like it's possible to represent anything with it, especially when we useActor composition systems. But how to correctly distinguish what should be there? And not, okay, really good question. So I get a lot of feedback that even something like this can seem like overkill for app logic.

[36:00] And you know, sometimes it is, sometimes, you know you. You might not have an app that has a lot of complexity and you might not need to have a full state machine. I would, I? I. I like to think of a state machine, or using state machines in XState as basically like using an airplane. You know, millions of people use airplanes every day, but even more people use things like cars to get from one destination to another.

[36:00] Now, cars are perfectly engineered. For when you want to travel, you know manageable distances that are connected by land. So, if you need to go to the next city over or need to go to the store down the street, you might use a car or a bike or something else. But, of course, if you want to go from one continent to another continent, now, cars become extremely infeasible. So really, you have to plan ahead and think, are you going to be developing app logic that is really complex in nature?

[37:00] Or, you know, that might need that sort of structure, and it doesn't even need to be something that's really complex. If you want something where your primary method of communicating what's happening in your app is through events, then using an actor model is very useful. And you could even use it in simple ways. Like in this example, we don't need to use a state machine, we could actually use from transition. Or, we just actually released XState store, which also really helps with this, so if we install XState store, then this is another simple way of representing actor logic.

[37:00] And just I, I'll show this a little bit later, I'm just going to downloaded for now. But yeah, like I, it's sort of like a hammer, and of course, when you have a hammer, everything looks like a nail. You don't have to use it for absolutely everything. But the more you practice with it, the more it, it. It becomes the second sense where you understand, okay, this type of problem space is something where I will definitely need XState, or something like a state machine, even if you're not using XState.

[38:00] Jeremy says XState sounds like an object request. Broker. IED used to be familiar with that term, but I forgot it. Extremely simple and extremely useless was my last performance review. It's great. Would you expand on how to compose X8 state machines? Please remind me later, and I, you know, I, I, I will, let's see. Currently, it looks like a reducer without a switch statement, and yeah, actually, that's a very good point.

[38:00] You could definitely create your own state machine where you have just a switch statement, you know? Function feedback, reducer. State event and then you could like, switch, but here's the difference. You're like, when you actually have a state machine, you're not switching on the events type, you're switching on the finite state value. But in this case, it would feel pretty similar. So we could basically create a switch statement like this, where we have feedback. update, and then we update the feedback.

[39:00] And you could definitely do it like this. The lines of Coder are actually pretty close to the same, so if you like using switch statements, you could do that. But there are benefits to having it in an object, which I'll get to pretty soon. Okay, see, do I get it right that there is no way anymore in V4? To couple contexts with states, using discriminated unions to enforce contexts having certain values in the certain states?

[39:00] This is something that we're still working on. It's a really hard problem, but we will get to it a bit later. But yeah, so before I answer any further questions, let's continue on with here. And what with what we have over here? So okay, again, we have this very, very basic state machine that's not really doing anything special. And again, if you open the visual editor, you can see we basically have a single state and we have an update function.

[40:00] That's all it's doing is really, updating that state, or, sorry, updating, you know, the context of that machine. So it's not really doing anything special. But if we want to actually make a multi-step form, this is where things actually get pretty interesting. So I am going to, you know, make a few states. And, uh. So the first thing that we want are feedback for to have is sort of this prompt state, so in prompt, you know, it's just going to be asking you, did you like, was your experience good or was your experience bad?

[41:00] If it's good, then we go to a think state where we're just saying, Okay, thank you, but if it's bad, we go to the form. And regardless of which state we're in, we could end up in a closed state, and so this closed state. We could also restart, and, you know, just go back to this initial prompt. State and so that's why we're going to add initial prompts okay so this is our very basic state machine none of the states are connected but you could see over here that you know that we have these four distinct states of our multi-step form so if you could imagine the transitions we have prompt and when they click good we go to thanks if they click bad we go to form and in any states they could close it but especially in this thanks stat there will be a button where you could say okay thank you and then you could just close that and then from any stat we could go back to prompt so since we're teaching XState we're going to be relying on the code over here so yeah let's we make these transitions so on we have two possible events over here I'm going to let co-pilot help me a little we have on feedback. good which this the key of this on object is the events type so you could imagine let that we're you know sending type feedback. good so that's what that looks like and then the same thing for here so we're going to be sending an event object with type feedback. bad the target is the state that we actually go to so on good we go to thanks and on bad we go to form so just to show you what that looks like now we have this so on good we go to thanks on bad we go to form and then eventually we go to thanks again so that's what our seat machine looks like all right so on forms so we could go back so let's say for whatever reason you decided you know what I actually had pretty good feedback you know it wasn't as bad of an experience as I thought and of course you could submit the form too so submit target thanks and then you know basically on any states when you close it you could go to the closed states but in the closed states we could restart and go back to the prompt now how do you represent that something can happen in any state and before I do that let me show you what this looks like, all right, so we have a better idea of, you know, of our state machine, um.

[44:00] So we have our prompt, so when we have good feedback, it goes to the thanks states, and when we have bad feedback, it goes to the form. Which you could also go back and for between the prompts and the form, and then when you submit the form, it goes to the thanks Stes. And then at some points, we end up in the closed states, but we want to end up here from any states.

[44:00] And so this, let's collapse this for a minute and let's add an on object, so on close. We're going to go to target. And because it's a child state, we have to start with the dot so dot closed. And we'll get into parents and child states in a minute. But this is how you target that child state. Okay, so now we have a, you know, a bigger state machine. And I actually want to show you like, what, what?

[45:00] Each of the states end up being so AG2, I'm just going to show it here and this is going to be states. value. And so it's a it's a string right now, I mean it, it might be something other than a string in the future. But it shows that our first dates, you know, were in the prompt state. And so, what we're going to do is we're going to be adding, you know, just the different screens for that.

[45:00] So, I'm going to cheat a little bit here and just copy and paste some JSX. So turn class name. Oops, no cool feedback. And then we're going to, yeah, let's just put that prompt in there. I'm going to go ahead and delete what we did before over here and so now you could see, we have. How was your experience? We have good and bad? Oops, not dib. And I'm actually going to show what the state object looks like.

[46:00] So to do that, I'm going to use a pre- tag. And we're going to just, JSON., stringify the state, just to show you what we're actually working with. So, we have our value, and the value is prompt, and that comes. From us being in the initial state, where the initial state is prompt, you see, there's a couple of other things here. The two important ones are value and context. And in fact, let's set this to an empty string, okay, so, and let's reload that, there we go.

[47:00] The other ones we're not going to worry about yet. They're useful, but you might not need to use them for most use cases. These are going to be the two that you're going to be most concerned with. Okay, so now we want to transition states based on, you know, whether it was good or bad. And to do that, again, we have our send function, and that send function allows us to pass an event object.

[47:00] So for the good button, we're sending this event object. With type feedback. good, and over here, it's type feedback. bad. So if we click good, you could see, we don't have the screen here, but the value is thanks. So we transitioned from the prompts to the thanks states, and if we click B, you see that we transition from prompt to form. So, a useful way to conditionally show, or, you know, just do something based on the state value, is this states. matches, function.

[48:00] Now you could do something like state. value is prompt, and that is actually going to work pretty well. If you have a normal state machine, but XIT allows you to go a lot further and have states nested within states, nested within states. So the you know it, it actually might look like, like prompts and a child state and a grandchild state. And all of a sudden, it's no longer just the strength.

[48:00] So that's why we use matches over here, with prompts, and so, that way we could do something like, just going to copy paste. Let's have a little thanks area over here. So if the state matches thanks, then it will just say thanks for your feedback. So if I click good, it shows thanks for your feedback. And so, one question that, you know? If you're coming from TypeScript, you might be wondering like, how do we actually get this to autocomplete? because by default, it doesn't autocomplete?

[49:00] This is why the setup function. Is useful. So to convert, all you have to do is add setup from XState, add an empty object and I. I'll show you what goes in there in a minute. But this is actually going to work just fine. And then you create a machine from your machine. Setup, and setup is where you set up things like actions, guards, delays, all the fun things that make your state machine actors actually useful.

[49:00] But now you're going to see, let's see if this works. If I type here, it actually shows our options, so we have closed form prompts. And thanks, these are all of our states, so I could just pick one and it autocompletes just like that. So hopefully like this right now. This gives you a basic idea of using a state machine for a multi-step form. And there's still more that we need to do, but I'm going to pause here.

[50:00] For any questions. So so let's see. Javier says. I've applied state machine patterns such as debouncing and throttling. Credits to Baptist Devasier, a really awesome person, and his examples. Is there an a plan on adding additional pattern abstractions, to the actor methods? This is something that lives in Userland, but I could see us adding helpers for that. There's a lot of patterns that you could use with actors, and, in fact, actor frame Frameworks such as AA employ these patterns.

[50:00] And it is a huge source of inspiration for that. Eric says. The reducer is a state machine with a single state, you know, one that just updates the context. The value of X8 comes from not listening to certain events when in certain states. And, yeah, so I do think that's definitely important, and if you wanted to make a state machine without using exit, you definitely can. In fact, just mention it on Twitter and I'll probably link you to one of my articles I've written that's called, you, I think it's called you don't need a state machine library, because you really don't.

[51:00] If you have, like, you know, function, feedback reducer, you know, you have your state event and you want to emulate this exact same thing. We could do something like, switch on the states. value, and then let's say it's case. Prompt then we could switch on event. type and let's say that it's you case. Feedback. good, uh. So so basically we could do the same thing. It's just that this is a little bit for bothast.

[52:00] And this currently does not let you do this. Which is actually visualizing, the state machine. So, you know, I think that's extremely useful, just the ability to see, okay, here's how all of the states and transitions are connected with an object. You could do that pretty easily with a switch statement, not so easily, especially if you're trying to define your own, UH. State machine without any sort of patterns. And also nothing here enforces the actual state structure of your state machine, it's just switch statements.

[52:00] Nothing is saying that you must useState. value and you must use event. type. So XState just provides a little bit of structure on top of that. And so, yeah, that's why it. It basically is just a producer with a switch statement. But honestly, X8 is a lot, lot, lot more than that.

[53:00] Hexy Meter asks, do you have any example of what is the proper way to use this? With? React query? So, one of the best parts about just the actor model in general is this abstraction that everything that can happen is in events, which seems like a topology. That's literally the definition of events, which is something that happens. But if you have, for example, a useQuery over here, like H, equals, useQuery, you know, and you have, like, your query over here.

[53:00] You could do something like put in your fa, my favorite hook, useEffect. And like, if data comes in, you could just send, type, you know, data, and then just pass the data in there. And so everything is abstracted in this single abstraction called an event. And so, you know, you don't have to hook any fancy callbacks or anything. Everything is just you're sending an event. And so that's how you could interact with Ed query, or really any library for that matter.

[54:00] Now, if you want to get more advanced because of the different types of actor logic, you could create such as promise actors and observable actors and things like that. Then it becomes very possible. To, for example, in React query, use the query clients directly and just create actor logic from that. Alex says thanks for letting us watch a nice presentation on a Friday morning. Absolutely no better way to spend your Friday than listening to me Babble about state machines and actors.

[54:00] But I really appreciate all of you being here, Jared says. So the setup function is really only needed for TypeScript and autocomplete, or is there a reason to use it when just in a pure JavaScript project? Yeah, I'll talk about that little briefly, but we haven't really gotten into actions just yet. But the setup function is for setting up things like, you know, not only just your types, but also your actions.

[55:00] So if we want to say update, feedback, then we could do something like this. But also your guards, delays, and especially your actors as well. And this replaces the previous pattern in V4, where you would have this as a second. Arguments to create machine because it's in a setup function over here. Now we have really nice TypeScript autocompletes for that. And in version six, this is going to be the way moving forward.

[55:00] We're not going to have those other options of having it as a second argument. So, whether you're using JavaScript or TypeScript, it does become, you know, pretty necessary to have that. Up there anyway. So it's just something that is good to get used to. Okay, how do you use match in a case where two states have the same name but are nested? So it's not very obvious at first. So, let's say you have, like, actually, yeah, that is a good question.

[56:00] You know what, I, I'll just show that over here. I know we're jumping a little bit ahead here, but this is good. It's a nice two or three. Our workshop, so we're going to be diving into all the parts of XState. So let's say that we have an initial state of loading over here, and you know, we have a loading state and a ready state. And so these are child states. So if you're new to XState and statecharts, all this means is that you could have states that are inside of states.

[56:00] So, you know, really? Good, for organization and reducing the number of transitions. But yeah, so, uh? They were asking the rude Sandstorm, guessing that's not your real name? You know? Let's say that we have a loading state inside a prompt, and we also have a loading state inside a form. So how can we do something like, show a spinner and I'll just have spin, spin, spin? How could we show this if we're in one of those loading states?

[57:00] So one thing that you cannot do is you cannot do state.. Matches like Star. loading, that's that's not going to work, you know? If you really want to like match. On specific child states, you could use an object and let's say, prompt, and what's awesome is that TypeScript should. Oh, I have to do this. There we go, we have our states AutoC completed there, so we have, you know, prompts loading. And then we could show the spinner.

[57:00] So, yeah, so, and let's put this up here. Okay, so we just going to show spin, spin, spin. Actually just for fun, we're going to. This is another cool XState thing. After a second go to ready, okay, so now it'll show spin, spin, spin for a second and then disappear. But what if you wanted to do it for this loading state as well? So these finite states can actually have tags? So, you know, let's add a tag and let's add loading.

[58:00] Like, that's just. It's sort of like a class name, so I'll just say this is like a class name. And so what we could do is put that same tag on, on this date as well. So this also has loading. And so that means that we could even call this something different. We could call it pending, for instance, and so when we call it pending. Now let's say that we go to the, let's reload this.

[59:00] We see spin, spin, spin and oops. That's supposed to go to form, but I don't think we have form yet in here, so I'm just going to go ahead and add that. But what I'm trying to explain is that you could actually, instead of having this state matches, prompt loading, you could say state. hasag and then just pass loading and so. That way, it's going to match any of the states that have that tag.

[59:00] So see, we still match spin, spin, spin, and, let me just add this form in here real quick, and I'll just get rid of these. So now spin, spin, spin, it's going to show that spin thing again because we were using the tag.

[1:00:00] And Baptist says thanks for making the webinar. David, thank you all for participating too. Okay, so let's continue, with our, with our state machine. And so I'm going to delete the things from the, the previous examples that I just showed. Okay, so again, we have our, we have our feedback machine. And in this stat, there's two things we could do. We could send feedback. good, which takes us to thanks, or we could send feedback. bad, which takes us to our form.

[1:00:00] So now let's actually get into that, because it's something that we learned already, which is how to update context. So yeah, I am just going to copy paste our JSX from here because no one wants to see me type that all out. But yeah. So we have our text area and just like we showed in the beginning, we have this. Onchange events handler, which, you know, grabs that on change event. And, it provides the value of that text area that we could just place, right into the context.

[1:01:00] So again, we would go here and now we have this, on feedback. update and this. We're going to have an assign function, so actions, oops, assign feedback, and then in here, just to do a deep dive on this assign, sorry on this assign function. You could pass it either a partial context, or you could pass in, like, the entire context. So, now this be, this starts to look like a, like a mini reducer.

[1:02:00] So we could actually say, return feedback. This is just going to be events., what do we call it? event. value. And so what that's going to do? Let's just, show you over here. We're going to show the states.. Context., feedback. And so now, just like before, we have the same, you know, the same context being updated because we're. Sending those events, and those events are changing the context. In the state machine.

[1:02:00] So yeah, let's just get rid of that. And yeah, so oh yeah. I was talking about a sign. So we have this, you know, this events that we're passing in, and you could use a sign as a function like that. What you could also do is assign individual context properties such as feedback. And, you know, we could just return so real quick. Over here, you get a few things, you get the, you get the context, you also get the event.

[1:03:00] And, you know, in more advanced use cases, there's other things you could use inside of here, but these are the two main ones that you would want. So over here, we could just return the events. value. And, for instance, if you're adding to a to-do list or something, you know, you might have, like, return. Context. todos do conat like events. Todo, something like that. But in this case, we don't care about the original context, we only care about the events that we're receiving.

[1:03:00] So, another quick trick. I'm actually going to just so that we could work on this states, I'm going to set the initial states to form. And so that way when we reload, it's actually going to start in this form states. So now we could type things. We see it over there just to see that it is updating in the context. Although I guess we don't really need it there, because, or we don't need it here because you could see it here.

[1:04:00] But you might have noticed in the original feedback form that this was actually disabled, you know, if there was no context. So the way that we actually do that is by using what's called a guarded transition. And basically, you could think of this as a fancy if statement, but this guard basically prevents a transition from being taken, so in submit, we add a guard by the guard property. And then we grab the context and we say we only want to continue if the feedback. length it's trimit to, and, yeah, we.

[1:05:00] We want to only allow this transition to happen if the thanks or sorry, if the context is greater than zero like. Once we trimmed it, see over here, going to remove this. So now if this is empty or even an empty string and I click submit, it's actually not going anywhere. So, you know, it's not transitioning. This is one of the really important things about state machines is that in event, if you send it, it's not actually going to do anything.

[1:05:00] Unless, the transition can be taken. So, this makes, state machines really, really robust. So, for example, if you're submitting a form and you go to the submitting states and the user. For example, if the button is not disabled and you click a million times, it's not going to submit a million times. Because there is no transition for that submit event, so nothing is handling that. That's a mid-event. So it's a really, really good way to, you know, just to make more robust application.

[1:06:00] Logic. So, yeah, uh. One of my favorite features of XState is that, you could call States.can. And basically, instead of saying, like, oh, or instead of duplicating logic and saying, this should be disabled if state. context. feedback, um., trim.. Length is, you know, zero ETC like that is already encoded in the machine. Basically, what we're really trying to ask here is, are we even allowed to submit? So that's why this date..

[1:06:00] Can you pass in the events that you know you want to happen next and where we're disabling it? If this event is not going to cause a transition, so of course, if we type something, it will cause a transition. So that's the magical thing about this is that St Thatan is peering into the future. It's saying, like, if I were to submit this event, will anything actually change? Like, is there any transition for that?

[1:07:00] And you know, if there is, then that evaluates to true, if not, it evaluates to false. And so that's why, you know, Le, let's say that, you know, we're. We're disallowing a bad word or something, so we could actually change the logic in here, we could say, or, context., feedback. includes that, so, if it has a bad word, so now, my experience was really, really bad. Oh, maybe it's not includes. What was it again?

[1:08:00] Wow, but anyway. Yeah, you could add other logic to it. Trying to think, actually, let's get co-pilot's help, uh. Feedback includes string bad. Oh yeah, it should. Oh oh, sorry should be an end. I'm sorry. So anyway, really, really. Oh uh. And it doesn't include bad. Wow, okay, so really, really bad. Now that's going to, you know, disable that. So now all of your logic is centralized in a single place, you know, which is extremely useful.

[1:09:00] So if I save that now, we're allowed to, to do that. So, yeah. One cool thing about XState, or useful thing rather, is that you might be wondering why this state machine looks very JSON Likee, and that's because one of the goals of XState is for your entire machine to be serializable. And so what that means is that you could basically read it from a JSON object. Or you could, you know, store it in a database, or, edit it visually and things like that, and depending on your taste, it might actually feel a lot better than having multiple nested switch statements.

[1:09:00] Or, even worse, having this logic be all over the place. Now, because functions are not necessarily serializable. There 's there's a way to actually specify this function in the setup and reference it later, so we could. I'm going to just cut this and say feedback valid, and so now we are going to add it to the setup feedback valid. And then I'm just copying and pasting it over there. So this, first of all, it will actually autocomplete.

[1:10:00] So if we have type and then press our quote mark, it says feedback ballot, so we could actually choose that, you know, so that's actually pretty useful. We could even do the same thing over here, so say, update feedback, and then we could just have this as an action over here. Now. I actually really recommend that you stick with defining things in line first, and then once you, once your logic is solidified, then move things out into setup.

[1:11:00] Just because it's a lot faster to work with, you know, just your state machine and defining things inside of there, rather than, you know, having to think like way ahead of time and thinking, here's all the actions. We need, here's all the guards we need. Because you're not always going to have all of that logic, all of that knowledge up front. So yeah, I will pause there for this, okay? Um? Muhammad asks, is there any example repo for backend?

[1:11:00] And the answer is yes. If you go to, just see how this works, will it work? Okay, it will not work, but that's okay. If you go to the X8 repo and I'll actually open the screen to show you over here, let me just go ahead and share, share the other screen. So we could take a look at some examples. I have way too many Taps open, so this might take a couple.

[1:12:00] [Music] Okay, so if you look at the X8 repo and let me just zoom in a little bit here, actually, I'll just do this. Oops, not that one, this one. Then we actually do have an examples folder right over here, so if you click into examples, you're going to see actually a lot of examples.

[1:13:00] And there's many examples that actually start with workflow. And so these workflow examples actually run on node, so they don't even run in a front-end framework at all. Of course, if you go to the ones that start with, or contain the word React, then these all you know, these, these are all reacts related, uh. We also have things like express workflow that show you how to make your own little workflow engine in express.

[1:13:00] But if you were to click into any one of the workflow files and then go to Main.Ts, then you will see the state machine in there. These are actually all inspired by examples from the server, the CNCF server list workflow specification. So we have our setup over here, and then we have some actors, and then we have our seat machine. If you want to visualize these by the way, and I, I actually just silently made this free, so you could just use it.

[1:14:00] If you're logged into Stately, you could go from GitHub..com to and when you go to state. New. I'm just going to go ahead and import code. I will paste it in there and then you'll see that we actually have our entire state machine visualized. In here. So this is a simple backend workflow where we start, in application, and then, if it's successful, we go to the end. Otherwise, we go to reject.

[1:15:00] And there's also a guard at the beginning where you have to be over a otherwise it just immediately rejects. So this is one of the examples, again from the server list workflow specification. But yeah, so there's plenty of examples inside of the X8 repository itself. Now there's also templates too, and these sort of act as examples. So there's one for reacts Felts vanilla and view the vanilla ones. You could, I mean, use those in the back ends, too.

[1:15:00] Nothing in XState ties you to the front end, so XState is completely agnostic. Whether you're using it in a front end framework or library, or even in the back end, doesn't matter. So, yeah, hopefully that answers that question. I'm just gonna. Go ahead and share my other screen. This code. Real quick, all right, let's find it, there we go. Okay, can do this. All right. Let's go to some other questions real quick.

[1:16:00] See, there's a lot of questions, honor says. I often have actions to clear the context. For example, when resetting to an initial state. Is there any convenient way to achieve this, like a reset initial context action? Perhaps? In X84, there used to be, but honestly, one of the simple things that you could do is this. So let's say you have your context over here, we could just move this up here, so con context equals.

[1:17:00] And then we have that feedback. And then I'm just going to have this reset, action over here, and I'm just going to assign that to contact. And that way, you know, we could have like, feedback. reset. And this is going to be actions reset or type reset again, the habit of making an action object so that we could add parameters later, if who wants to. But yeah, that's all you really would need to do for a reset action.

[1:17:00] And it could be done in Userland, or user land. And, yeah. So it's not something, something that's built into XState, but it is something that's, simple enough to do. And actually this. Is pretty useless over here, so I'm just going to move this right over here. And, actually, let's add that to the form just it's a good exercise for, like, how you would do this in code. So let's say that I have a little reset button over here, so button and reset, then onclick.

[1:18:00] I would just send type, feedback. reset. Thanks, co-pilot. So now let's say I'm typing a lot of things, I press reset and it takes me back. Now. This is not a controlled component, which is why it's still showing here. But yeah, you, you could imagine if you did make it controlled, that's what you would do. So, if I have the value as state. context, that feedback, then you'll see that it actually does reset it.

[1:18:00] So, yeah, all right. D asks, what plugin do you use for AutoC completion? It seems to predict what you want to type. Very well. So again, X8 with setup will autocomplete, and this is just using vs. Code intellisense. It will autocomplete, like your actions, your guards, and if you're using the setup function, it will autocomplete. The value inside of states. matches. But for the things where it's basically magically telling you, oh, okay, this is probably the code that you want.

[1:19:00] That is using, co-pilots. So, GitHub Co-pilot actually uses AI and LLMs to predict, you know what I'm about to type? And I want to let you in on a little secret, which is, GitHub. Co-pilot is really, really good at XState, and the reason it's so good is because XState has been around for eight years. It's trained on all of the internet data, so it basically got a chance to read. Like, thousands and thousands of state machines that people have created in X8 version 4 and X8, I believe some in X8 version five as well, like with the newer, the newer models.

[1:20:00] So, yeah, go ahead and try co-pilot. It understands XD pretty well, BTI says. XD being a big JSON object makes it easy to generate a state machine from other formats. Like nodes and edges from React flow, and, yeah, I actually really love React flow, also known as XY flow, it's an excellent, way of creating these nodes and edges types. Of connected graphs. But yeah, I, I understand how the big JSON object could be offputting.

[1:20:00] But really, we're trying to find a universal way of defining these state machines, and Jason is really the closest that, you know, we could get. XState absolutely could have been made in some sort of, dot chain Builder syntax type of formats. But the problem with that is you lose things like, you know, bir directional editing or the ability to just copy and paste state machine definitions even from other languages.

[1:21:00] So, yeah, I. I think there's a good amount of trade-offs that we had to make when choosing a JSON as a format for Xade. But I'm I'm pretty pleased with it. If you could just get over all these little curly boys floating around everywhere, I'm sorry. We're not Python, so in JavaScript you have to deal with that, nicholas says. I believe there are two main ways of doing exit in the back end.

[1:21:00] The first is through short Liv request response processes. That involves loading accuracy from a database, hydrating handle, handling the event, and saving. And the other way is long lived actors. And I think, yeah, that's actually a really, really good point. If you go to the there's, oops, I'm in the wrong thing. But there is an express example that shows you how to, basically, restore the states, or, sorry, persist the states to something like MonGod, DP, or even your file system.

[1:22:00] Restore that state and then continue the state machine from that state. And so your state machines could really be serverless in a way. Sorry, okay. When we have nested states within states and each can have its own context, how can one access the context from a deeply nested state effectively? So, context, at least right now, is that there's only a single context, and that is, you know, for the entire state machine.

[1:22:00] So there is no such thing as nest context, at least right now. So, yeah, hopefully that answers that, okay. So to get persisted snapshot, uh. To work properly, we should move the logic to setup. I had some problems using it with the cyclical structure, it should work regardless of if you're using setup or not. But I'm happy to answer any further. Questions in the Discord or wherever else all right Hey Hario good to see you any plans on Angular examples I know that people do use XState in Angular we don't have an official package just yet but we do know that some people are working on that so we'll definitely have more and also if you just do a search for Angular and XState you'll see that people have made examples and even tutorials of how to use XState with Angular one of the cool things about XState is that because this feedback machine if you create an actor so in fact you get the actor from this third arguments over here you already have actor. subscribe and so in this subscribe method this actually implements a tc39 observable so you could technically just use the actor directly in something like RxJS and so that actually works pretty well entory asks can you split a large state machine into multiple smaller pieces is it possible to have child machines if yes what are the caveats of parents state thought matches sending events etc so like I alluded to earlier you could have nested states inside of states and that's something I definitely encourage as your machine gets bigger but doing something like you know literally just separating this and having let's say cons prompt equals like this object the small problem with this where you could definitely do this especially if you're doing JavaScript but developers tend to want the best of both worlds which is you want strong typings here and you also want the ability to like define this in a separate file but that's extremely difficult to do because it is completely separate from something like setup where you set up all of your types and things like that like how do you connect the two and sure maybe we'll find ways in the future but it just becomes a little bit difficult so that's why honestly like co code folding is your friend but also we're going to get into this in a few minutes but you could also just have different actors and you could encapsulate those logic into different actors and then read the state from those actors too Oleg asks how do set state from a state machine from another state machine?

[1:26:00] The first machine is the main one, the second one is some sort of background processing, can be start, which? which starts from the first one. So in general, I would answer this by saying that everything, like the only thing that could change states in an actor is an event. And that's why I love this model because it's so simple. It's just everything is based on an event, so that event, object, you send it, something is going to happen.

[1:26:00] Now. If you want some actor to affect another actor, the only way that could happen is that actor sends an offense, to the previous actor. And and that's it now. With steam machines and XState, you do have some nice affordances for subscribing to actors and updating the snapshot that way. If you, he wants to, and you know, we might get into that a little bit. But for most intents and purposes, you would just be sending events and that's the way that you change anything.

[1:27:00] So, really simple mental model, but it gives you a lot of play around with. You know, it's sort of like Legos, like, there's so many different ways you could put Legos together, but the concept is really simple. You have studs on the bricks and they connect. Okay, so let's actually continue. Let's see where were we? So we have our feedback machine good, bad, and we have our various STEs, so I'm going to get rid of this loading state.

[1:27:00] For now. We have our feedback or our feedback form, which has a prompt thanks, and we also have a form. We have our reset button that we added. But we could just get rid of that. And, yeah, let's also add one more thing, which is a way to basically close the form. So if I, yeah, let's just add this close button over here. So go to feedback and then we have a closed button where we send this type closed event.

[1:28:00] And so remember that this could happen in any state, so if we click good, we could go to close, we click bad, we could also close it from there. Now, let's say that, even though. This is, and just to visualize it again, even though this is a, you could call it a universal event or something like that. Basically, this close event is going to happen from basically anywhere, so in any states, we're just going to say, if the close event happens, then we go to the closed state.

[1:28:00] And this also teaches a little something about nested states, where, depending on which state we're on, like, let's say, we're on the form states. The way that a state machine is going to determine which transition to take is, it's going to start at the deepest child first. So let's say that we're in the form state and the close event happens first. It's going to check this form's own transitions, so that would be feedback., update feedback., reset the back transition and the submit transition.

[1:29:00] If any of those transitions are enabled by that event, it's going to take it. So, for example, if we have the back event, then it's going to take this back event. Because that's enabled in the form state, it's not enabled in prompt or thanks, or anywhere else, but only in the form state. This submit event. It's enabled in the form state only if this feedback valid guard passes, so that's why guards are so important, because they determine whether a transition is enabled or not.

[1:30:00] Now let's say that we get the CLOS events in the form state, so it's going to check all of our transitions. Feedback., update, reset, back and submit, and it's going to say, well, none of these transitions match. So then it's going to go up a level and we're going to check the parents, we're going to ask the parent state is close trans? Like, is it defined on your state? And it is so.

[1:30:00] It's going to go to closed, so that's why in any states, we could just go to close now if we don't wants that for whatever reason. We could basically make a forbidden transition, so we could define a transition that does nothing. So let's say that we have this close event. I could just put an empty object over here and that way I'm, I don't know if you could hear, I'm doing a lot of clicking.

[1:31:00] Close does nothing. And of course, we could useState.. Canan to conditionally show or hide, or even gray out that close button. You know, because it's not going to do anything. So that's how you could use a, you know, a. Basically, that's how you could define a global or not Global. But a top level event, and also, just, forbid that event from happening in certain states. Okay, so, let's actually get into, the meat and potatoes of XState, which is actors like we talked about at the beginning.

[1:31:00] Like I said, state machines can, spawn and invoke actors, so basically actors can spawn other actors, which could also spawn other actors. That's just part of the actor model. And so, what I want to do is actually, instead of going to thanks, I want to create this submitting state, so submitting, and just to give you an idea of what this does. We'll make a little dummy, UI to show, so we're going to go submitting, and I'm also going to add, let's see state. matches, submit.

[1:32:00] And I don't have a fancy spinner or anything, but I'm just going to let Co-pilot do its thing over here. So now, what we could do? Submit some feedback, submit it, and then it's in the submitting state. So let's say that we actually want to submit the form data in this submitting state. Here's how we could do that in the state. We could do what's called invoking an actor, so this actor could be a promise actor, it could be another state machine.

[1:32:00] But just to make things simple, I'm going to use a promise actor. So we invoke, and we set the source to from promise, like we showed before. And, you know, let's just make a dummy thing like this. Return, do this is optional. Like it, it doesn't really matter what comes back from the promise that is up to you and your logic. It, it doesn't matter. Okay, this is just because we don't have the L up XState.

[1:33:00] So PM latest, which actually does solve and you could have inline actors in here. But, yeah, so don't don't worry about that TypeScript error right now. Now this will still work and then we could say onone target thanks, so this is going to. Wait for one second and then it's going to return this object over here. And then we're going to go to the thanks date. So submit and then it says, thanks for your feedback.

[1:34:00] And so that is a very simple way of just invoking something like a promise that might hit some sort of API and, you know, eventually return back data. So now let's say that we also want to, you know, simulate an error, so I'm going to add an error state over here and typ scripts. Freaking out, that's okay, date. matches error. And we're going to say that, you know, something went wrong. So co-pilot just read my mind over there, and so one cool thing you could do is because everything is an event and that's the thing that changes.

[1:35:00] Stes. We could say after, let's say, let's say our time out is two seconds, we could just target the error state, so let's say this takes three, three seconds. Bad feedback submit all right, something went wrong because this was taking too long. So now let's bring this down back to a second. And you could see that, you know, it's actually going to go to. Thanks for your feedback. So that's another thing I want to quickly talk about is that in XState, you could define what's known as a delayed transition, so you could say after 2000 milliseconds, we go to the error states.

[1:35:00] This is technically the same as doing this on, and then we have a special event that's like X. after. 2000er, something like that. The details of this aren't important, just know that it is a unique state. I think technically it's also like, feedback... Submitting, like it's just a unique event. For this. And then we go to target error. But also what it's doing is it's going to entry. I'm just going to say, it's going to, tell Xat to send that event after a delay, and then on exit, it's going to tell Xat to cancel that special event.

[1:36:00] And so that's what's happening behind the scenes. But as a convenience, we have this after. And that is why when we're not in the state, so when we're not in the submitting states, and let's say that we're in. Thanks, first of all, the timer is cancelled, but even if it weren't Canell, nothing in the thanks Dat handles that, that event. So basic principles of state machines only defines transitions will cause an effect in a certain states.

[1:37:00] So, yeah, let's let's abstract this a little bit more and show you how to, you know, use it in setup. So we're going to add an actor here. And this is going to be send feedback. And then this is going to be a promise and that promise, you know, is going to call a fake API. And so now when we go back to here, we could autocomplete this to send feedback. So again, this is going to work and then it's going to say, thanks for your feedback.

[1:37:00] I'll pause there for questions. If you have any. Let's see, Javier says. I want to mention that the actors onone and on error.

[1:38:00] Allowing arrays of actions with guards saved me a lot of time thinking about fallback setups. Yeah, so that's something that is important to, keep in mind is that, you could have arrays of actions. This might be simplified in X8 version 6. We're we're starting to plan that, but with actions like, currently, let's find a good action over here, all right. So we have, you know, let's say that we have type update feedback over here.

[1:38:00] It's plural, and plural implies you could have more than one, which is absolutely true. And so we could do something like, like, I don't know. Console.log updated feedback. And so you could have multiple actions in here, you know, we could also do things like raise events and you just things like that. But yeah, you could definitely just have multiple actions in there. Currently, in X8 version 5, by the way, there is a, lightly more convenient way to define multiple actions, and especially actions that could conditionally happen.

[1:39:00] And I, I feel like it's more natural. I'm just going to make a silly example over here. It's called ONQ actions, and with ONQ actions, you get this cool ONQ function that's a little bit hard to type. Or at least me. It's like all these weird U's and E, and then you could ONq, you know, actions. Like normal, so we could have TypeScript coming in clutch here, you know, just in action, you could also just, on Q in a sign action.

[1:39:00] And so that's going to work, you know, pretty naturally, you could also have conditions too. So if, like, let's say we're reading context over here, so if, context. feedback. length is greater than zero, then we could onq. Like a send to so, so we could, we could do things like this, and this becomes a more natural programming model. Because, you know, it feels like you're imperative ly executing these actions. But because it's called on Q actions, it's basically saving those actions to be executed.

[1:40:00] When the interpreter actually decides, okay, these actions need to be executed. So, yeah. If you want more dynamic actions, look into ENQ actions in the documentation, and so, the documentation. If you go to state Le. AOC, you should find absolutely everything there. So, yeah, in short, you could have multiple actions, okay? BST says delay transitions are one of the best features of XState. It makes managing timers so much easier. Thank you for that.

[1:41:00] Yeah, if I have time. There's another example where we could actually make a timer with X, or I could actually show some of the examples there. Honor says, sorry if I missed it, but is on Q, a bit like, pure, yeah. So in X8 version 4 we have this awkwardly named function, and I say, awkwardly because it's my fault. I'm the one who named it. Called Pier, and so Pier allowed you to return an array of action objects.

[1:41:00] But ENQ is a more natural form of that, because you're enuing whenever you want. So it's doing what pure does behind the scenes. It's just a little bit easier to use, and that says on Q actions. I love that. The state team added this function, it's way better than pure, so, just like I mentioned, it's basically doing the same thing, just in an easier way, Thomas says. Is it possible to split the actions in a different file?

[1:42:00] Do you think it's a good idea? I think, so. So, and that's actually a really good, you know, segue into, into. This next part, which is using parameters or parameterized actions and guards and things like that, so let me add some types here and I'll by. By the way, everything that I'm talking about in here is in the documentation. So let me just add feedback string, Okay, so let's take this card.

[1:42:00] For example, if you def find the guard inside of. Here. We have context, and the context is strongly typed to have feedback as a string. So then you could call context. feedback. trim. Lan zero. Let's say that you actually wanted to define this in a separate file and by separate file. I'm just going to put it at the top here. So we're going to say, what's it called feedback bot? So const.

[1:43:00] Actually, let me scroll back up here. Feedback valid equals this. Now, there's a little bit of a problem if you define this in a separate file, you need to know what this context is. It might not be that big of a deal because we could just type it context, type of context, and then everything should be. Oh well, it's the same name, so let's call this, initial context, and then we could call this type of initial context so you could do this and TypeScript is happy.

[1:44:00] It says, Okay, I know what the type of the context is, everything is typed. But then if you get the events and everything else, then things become a little bit trickier. So there's actually a different way called parameterizing actions, and this is probably going. Actually. This is definitely going to be the default in XState version six, where instead of providing the entire context, only provide what's the actions need. So the way we could do this, and which makes it really easy to.

[1:44:00] Define actions and guards and actors and separate files is, or, sorry, just actions and guards in separate files is to provide parameters. So I'm going to define my parameters and I'm going to say all I care about is the feedback. Then we could just say pam. feedback. trim. Don't worry about this. It's just typescripts being really, really, annoying. But, we're ignoring that first argument and then we're saying we only care about the parameters.

[1:45:00] So now how? Do we actually bring those parameters in? So, see, we have feedback valid over here. So now we see that we have an error over here, and that's because there's a nasty TypeScript error. We're missing parameters, so now we could say that our parameters. And we could pass it the function here and grab the context, and then we could just give it the feedback from that context. So basically, the guard or the action, wherever you're deciding to use parameters, is only declaring what it needs.

[1:45:00] It's not saying, give me the entire context or the entire events, because that is implementation specific to the state machine. And actions and guards, really. They should just be simple functions that a guard should return, true or false, and an action should just do some sort of effect. Without having to care about everything inside of context or events or anything like that. So that's why I prefer to use parameters. It just provides a really nice separation between, you know, just between the different ways of, like separating out your actions and your guards.

[1:46:00] So okay, let's see, Paul, shop or Shet stop, sorry if I mispronounce your last name, asks. What is the difference between actions and effects? So, the docs explained this too. But actions, and, things like invoked actors, both of these are what calls an effect, and an effect is just something that happens external to the actor. And uh. Actions are fire and forget effects, which means you don't care about the results of them unless they're special actions, like a sign.

[1:47:00] So if you're doing something like, do something and you're just doing a console.log, hello. This doesn't affect the machine at all, it is a fire and forget side effect. However, if you have an actor like send feed back, then it's something that's managed by XState, so XState does care about. For example, what the resolved value of this promise is, or if it's for an observable or something else, then it does actually care about.

[1:47:00] And it is, it still has this connection to this long lived effect. So, in other words, let me just open the TA draw. You could think of an action, so this is an action where, let's make this black, so. In action is like this fire and forgets, so fire forget effect. Now in actor, it's a little bit different, so an actor, it might return. So it might, you know, send events back.

[1:48:00] Or be managed by the parents, so managed by parents. So hopefully this distinction makes sense. But overall, all of these terrible are effects, and so effects are just things that happen outside, outside the actor sense. All right, and thanks for the explanation. Okay, so now let's get back into actors, and this is where we're actually diving deeper and deeper into XState. So, you know, just like before, we have this, from promise actor, uh.

[1:49:00] And right now it's not really doing anything, it's just setting a timeout, then returning, returning a status. But what if we actually wanted to return the feedback? So the way that we could do this is by declaring input, which is a really, really good feature. Of XState I, I sound biased, but you know what I mean. And so let's have feedback as a string, and so this is how we type it.

[1:49:00] It's going to be destructured from an object and then you could just say that the input is going to be an object that contains a feedback property, which is a string. So now, you know, we could do things like console..log, you know, sending feedback, and then this is strongly typed, so we do have this input. feedback. And you might call some sort of API, so you might like, Oh, wait, fetch, and then, you know, some URL.

[1:50:00] And oh, forgot that, that's a thing, and then you just return, you know, something like, did it work? True? I don't know. Just whatever you want to return over here, or feedback submitted, and then this is whatever, so basically just whatever comes from that promise. This is implementation specific to your use cases. But now we have to actually specify this feedback inside the send feedback. And you can see that TypeScript is at least telling us, hey, there's something missing here.

[1:50:00] It's. It's really a terrible TypeScript error, but you are missing input, which is why it's yelling at you. We do have to do something about those TypeScript errors. It's it's very hard to. Control what TypeScript tells you when something's wrong. But what we could do is we could specify the input property on the invoke object. And say that our feedback, which is strongly typed, should come from context. feedback. And then, what we could do actually?

[1:51:00] Let's, let's do this. So, I'm going to have feedback string and then receiv received feedback also a string or. We'll also make it null, so let's make our initial context. Received feedback null. And I'm just going to go ahead and move this back over here, just to make things a little bit simpler. Okay, so our promise actor? Eventually, it will resolve, and it will resolve with our feedback and this is something that we could actually react to, so we could have an action and we could assign and we could say our received feedback should be, events. output, and this event. output is going to be the result of that promise, so our send feedback, promise, we're going to have an, an object that comes back.

[1:52:00] Say, submitted feedback, and that should be strongly typed as well, so we have feedback submitted over here and then we go, to thanks. So now, in our actual form, or, sorry, not the form, but when we actually submit it. We see our state. context. feedback. Instead, we could have state. context. received feedback. Or, or maybe it's missing, but because that could be a string or n. So now if we type in some feedback and did I put this in the wrong place, yeah, I might have.

[1:53:00] Okay, so let's go back to our thanks date. Here we go, we press submit and then we see submitted feedback, which comes back, from the server or wherever. Uh. So, if we like, just redefine this, just to make things a little bit more clear, and just do input. feedback. to uppercase and just make all of it. Just screaming at you, bad, I didn't like it. Now it just screams at you. So this is what comes back from the server.

[1:54:00] So, yeah, that's where, things like input and output, which are just very related concepts are useful in XState. So, yeah, I'll. I'll pause here. For any questions. Answer. Drink water, Okay, let's see. If there are any questions over 400 of you, no questions, great, I guess, okay, so, I, I, I guess. I could take this opportunity to dive a little bit deeper into state machines, and more specifically, statecharts, so statecharts extend state machines, but statecharts are state machines, so that they're basically the same thing.

[1:55:00] It's just that statecharts are a way of specifying more comp complex state machines. But also a way of organizing it in a way that, like, you don't have a an explosion of transitions or a lot of complexity. It's a way to organize, organize your states and transitions in a state machine. So, for example, let's say that our prompt actually had, three different states. And so I'm going to, just edit it over here.

[1:55:00] Bring this down a little bit so you could see, and then, yeah, let's change this up a bit. So, let's say we have, see, how do I want to do this?

[1:56:00] Okay, so let's say that we have three different substeps inside of our step. So, you know, we have step one. And so I'm just going to call this, prompt step one. And then we're just going to copy and paste this, just make this a little bit easier. So now we're going to have prompt step two and this is going to be prompt step three. Okay, so then we're going to add some states over here.

[1:56:00] So initial step one dates we have step one, step two and step three, and then for each of these we're going to add. Like, the feedback over here is going to go to step two, regardless of which one you choose. This one is also going to go to step three, and then this one is going to go to either thanks or form. Let's see if this works. Let's see what did I do wrong?

[1:57:00] Let's see, Jason I. I really love using JSON. string device date and then just putting it on the page. Just because it's such an easy way of, you know, debugging these, and so if you're debugging your SE machine, you could either log this. Or actually, I might be doing something wrong. Let me double check over here. Oh, oh, okay so. If you were to open this in a browser, you would actually see that.

[1:58:00] It, it's going to tell you that some transitions aren't possible. So, for example, you know, thanks is not a child state of this prompt date. So, in fact, if we were to visualize this, I'll show you the problem over here, it's not even going to visualize. Because, yeah. So what we could do instead is, uh? Target these states by ID. And so, to do that, just like in HTML, you would add the hashtag, pound, sign, whatever you want to call it, and also give an ID to these Stes.

[1:58:00] So if we go to the thanks state, give it an idea of thanks. And so now things should work there. We go, okay, and now I'm debugging it twice, so let me just get rid of that. And so now we have, we're in our prompt states. So, good, good, good, and then it takes to. Thanks for your feedback. Then we could restart over here and then so we could just keep going through all of those states.

[1:59:00] And so these are. I know it's a bit of a CONTCT example, but these are child states inside of that parent state, and this is what that looks like. So let's a layout real quick. We have this prompt and we're in this prompt state, and we say, you know, we also start in the step one state. So basically, when you enter the state machine, it's going to find the initial state, which is prompt, and then it's going to find the initial state of that initial state.

[1:59:00] So it's recursive and it's going to say, Okay, we're on step one. So why use nested states? You could use it as a method of organization, but also, like I told you previously, it does reduce the number of transitions. So let's say that, let's say that in any one of these states, so step one, step two, step three. They had a bad experience, and we want that bad experience, that events to always go to the form, no matter which state we're in.

[2:00:00] So the way that we could do that is, you, let's get rid of these and let's define this at the top. Level like we did before so we have on feedback. Target form so now our state machine is going to look a little bit different and let just try to try to show this to you here's our form and so now we have this feedback. bad by the way this is the old the old visualizer which is why it looks a little bit crazy or there we go where is it where is there we go feedback thought bad so regardless of which state we're in so it doesn't matter if we're in step one step two or step three if we get this feedback. bad it's going to take us to the form and this is because of something we were explaining earlier where let's say we're in this state and we get feedback. good then it transitions to step two but regardless let's say that we get feedback. bat first we check the states inside like did we get a feedback. bat events or do we have a transition that is enabled by that event we don't so we're going to go up to the parent is there a transition enabled by feedback. bad there is so we are going to take that and we're going to go up to form so the effect of this is that no matter which state we're in sorry that's a little big no matter which state we're in if we click bad it takes us to the form so that's one of the valuable things about having nested states is that you don't have to have a transition for every single one of those child states to go to a specific state instead you could basically say you know or you could delegate that logic to the parent state so I know that was a lot to take in and honestly having the more advanced features of statecharts such as nested states and parallel states and all these other things that we did didn't get to just yet they're very useful if you have more complex logic requirements they're not things that you should start with necessarily because your logic might be simple and it might not need any of those complex things you might just need a simple state machine so I will pause there and go to questions.

[2:03:00] So it's a bit confusing that an action can assign a value to the context while being considered Ed as a fire and forget thing. Honestly, this is because of, XState tries to adhere to the SCXML spec, which is statecharts for XML. Which was, it was, made part of the W3C in 2015, so it's a pretty old spec. It was started even before then. And in there, an assign action is actually also an action, too, so it is something that's in the executable content.

[2:03:00] Of a, of a, of a transition. So, it. It's honestly just the most convenient place to put it. It's something we might reconsider in future versions, but, for now, it that's just, you know, a convenient place to put it. Paul continues to say, uh. For me, an action is more like a thing to tweak the state a little, while a spawn actor is a thing that has been triggered by the machine.

[2:04:00] Entering Estates. Am I correct? Sort of, so. Only the assign action would tweak the state a little. You also have actions that might not have any direct immediate effect on the states, and these would be things such as like a log action, a send to action, where you're sending an events from one actor to another actor. Or, you know, e. Even a raise action, which raises an events to be processed by the machine.

[2:04:00] Which is pretty close to immediates, but it's still something that happens externally and then comes back to the machine. And a spawned actor, you could either have it, you know, be invoked, or you could have it be spawned.

[2:05:00] And those do different things. It's more of an advanced topic, but, yeah, there's a little bit more of a distinction. Uh. Daniel asks, is there a visualizer for VS code for X8, V5 already and not yet? And so I'll I'll talk about that a little bit right now. And right now, the extension, so the VS code extension that you're seeing it does work partially with X85. Which is why we were able to get it to work.

[2:05:00] Right here. Now. The tricky part, and this is also a problem with the existing extension, is. The bidirectional editing. So there's a lot that happens over here, where, you know, if we move things. Of course, the code won't necessarily change, except for this big, ugly layout string. However, if we do things like add states, add transitions, then that's where we basically have to make surgical updates to the code. And this has actually worked pretty well, especially if you've been using the X8 extension for a while, you already know that, you know, for a lot of use cases, this works pretty well.

[2:06:00] But where it sort of breaks down is like, if you want to do custom things to your code. Like we talked about earlier, moving parts of your state machines to different files, even some of the actions and, guards and things like that, because there's many, many, many ways that you could edit your code. But, of course, in the editor, you have only a constrained way of editing the, the states diagram. And somehow, both of those need to stay in sync.

[2:06:00] And to get absolutely every edge case working perfectly is a very, very daunting task. And so that's what we've spent a long time trying to make it work. You know, just with all of those, regardless of if it's X8, V4 or V5, it just took a lot of effort. And, so if we are going to release a visualizer for X8 V5, it will probably either be view only. So you could, you know, visualize the state machine on the right, which is very, very useful.

[2:07:00] Or if you wanted to edit it over here and have it reflects back on the code. It's going to be more of a U, a complete replacement of the code, rather than doing surgical updates, just because that's going to be a lot easier to do so. Yeah, it's still something that we're slowly working on. But yeah, it's definitely an extremely tough problem to solve. If you've ever tried to do bir directional editing of diagrams and code, it's just it's a it's a hard problem.

[2:07:00] Thomas asks. Can we replace a child state with invoked actor? so you invoke an actor in a state, so they're not interchangeable? It's when you're in a state, for example, when we're in the submitting state, um. You know, we're invoking an actor, and you could also invoke multiple actors too, so I could also invoke something else here, you know, and do that. So that's why, you know, a you do have to have that invoked property when you're in the state.

[2:08:00] And Paul says, thank you. And maybe consider a Readon visualizer. I think that's what we're going to go for next. And yeah, I think that's a really good idea. Okay, so other XAT concepts, I'm trying to think there's honestly a lot to talk about. And there's not too much that we could fit in under three hours. But the basics, you know, you could cover in 5 to 10 minutes, which we pretty much did today.

[2:08:00] Which is how to create an actor, which is, you know, just something that has its own internal states, it can receive events, and, it can updated its internal state based on those events. You know, you could use from transition from promise and of course, create machine to do that. And then we're just diving deeper and deeper into state machines and statecharts right now. Now. So, here's, here's another good one when we are going through this form, oops.

[2:09:00] So let's say we have step one, step two, step three, and then U, actually, let's step one, and we want to go B. So let's say we were in step two and we click bad and then we go back. It actually goes to step one, which is a little bit unexpected. And so that's where we could use what's called a history states, and so the history states means go to the most recently visited child of this parent state.

[2:10:00] So I'm just going to call this Hist and type history and so now when we go back. And this is also going to teach you how to target child states. Instead of going back to the prompt which goes to the parent, we're going to target prompt do HIST, which is that history state. And so that way, what's going to happen is, let's reload. If we go to, for example, step three and then we click bad and then we click back, it takes us back to step three.

[2:10:00] So just going to show how this. Is visualized. It's a little bit crazy over here. So we have a history state and we see that for our sorry, let me just zoom in a little bit there, okay? So, in our prompts, we have a history state and this history state. All it's doing is remembering which one of these child states we were in. So if we go back, instead of going back to the parents, which will always go to its initial state, we're directly targeting the history state, which will go to whichever step we were just on.

[2:11:00] So you're not going to use this all the time, but there are instances where using that is, you know, really useful. And this is one of the original ideas of statecharts and something that's also specified in SCXML, which is why XState includes that. But, honestly, most of the time, you will not need to use a history state. Oh, and that answers, Wow, I read your mind, so that answers. Can you talk a little bit about history states?

[2:12:00] Cedric asks. Emit is also a really good thing to introduce in version five, if I'm not mistaken. Yes, okay, so that's actually a new feature of XState version five. Really, really good call, so let me go ahead, I'm going to undo this, and okay, so I'm going to, sort of do this impromptu here. But I think that this is a very, very important feature. Let's call this, function toast. So what we're going to do is we're going to make a really simple component that shows a toast when it rece.

[2:13:00] Or let's, you know, toast is a weird word.

[2:13:00] Let's call it Notifier, and so this Notifier is going to basically receive events and display them on the screen. So, we're going to return DIV and let's just actually let's make this strong, and we're we'll just put example notification here. This is. This is actually going to be fun because we're not only going to show you what EMIT is and how it's super, super useful. But we're also going to be showing you.

[2:13:00] Basically, how to work with these state machines and these actors in real life applications, and where, you know, you could express more and more complex logic in. A in a simpler way, I didn't say easier, but simpler. There's a difference. Okay, so let's put this notifier on the screen and it's just going to say example notification here. Make this a little bit bigger so that you could see it, okay, so example notification here.

[2:14:00] And fact. Let's give it a little color, not white, let's make it just orange, so that's way too whatever. We'll make it blue, even though it's not the exact same blue, but that's okay, we're just showing an example notification. And so let's say that we want to know when this form was submitted, but we don't really want to, like, be closely coupled to this feedback machine, like all this Notifier cares about is I received something, so I'm going to show it.

[2:14:00] It doesn't need to know about the feedback machine or any of these other actors, it's it doesn't even need to know about the actor, model or state machines at all. So it's a really, really good way of decoupling. So what we could do is, I am going to pass the act, or how should I do this? Yeah, you know what, I'm just going to pass the actor in here, and so because the actor is just an object, it's an object.

[2:15:00] With a send method, get snapshot, all of that you could just pass around. This actor reference, just like any other value, and so it becomes really, really useful that way. So this actor, really, it's any actor ref, which is something that XState does provide you. So you do have that type and you could do whatever you want with it. And we could, let's const notification we're gonna, we're gonna useState here, just because, you know, useState isn't bad it.

[2:15:00] It is useful for simple use cases like this. This is going to be string or null, and so return notification, show this, otherwise we're not going to show anything. So now we have no notification, but, we are going to receive it here. So now, in a useEffect, we could basically subscribe. So in, like before this feature was released, this was actually a little bit difficult to do. Where you wanted this actor to notify you of something, or basically emitted an events that.

[2:16:00] You listened to and cared about, but this wasn't necessarily easy, or it meant you dependent on the implementation details of that actor. So it was actually a little bit tough to do. Now with XD V5, there's a simple way by, using emitted events, and so what you could do is, say, Actor.on. And let's say we have a notification, so now we have the event, and we could, set the notification to the events.

[2:17:00] Do, actually, let's have it as message. Okay, all right, so that's basically all you have to do. And this, this is a subscription, so, you know, count. If you really want to do the cleanup, which you should, it's a good thing to do. You could just call that, just unsubscribe to it. When this component is turned off so that you don't have any, memory leaks or anything like that, okay, so now how do we actually emit, this notification event?

[2:17:00] Let's go to we're submitting onone when the form is submitted. We're going to do multiple actions. So one of them is going to be assign, the other one is going to be EMiT. And then we emit this type notification and our message is going to be feedback submitted. Now I am importing the wrong emit, which is why it's yelling at me. There we go, Okay, so we're emitting this events notification feedback submitted.

[2:18:00] All that, all that this is doing is just admitting it to whoever is listening for it. So now let's actually try that out. Hopefully it works. Doing this completely impromptu, but it is a very, very important feature to talk about, all right? So let's say we, you know what? Let's say we go through good, good, good. And it says, thanks for your feedback. There won't be any notification because, we, we, we didn't submit a form, we just said everything was good.

[2:18:00] So now if we click bad and we say something really bad and we click submit, you're going to see feedback submitted. So that's how you could use event submitters, or basically use XState as a very simple events emitter. Listen for that notification events, and then, basically consume this, you know, this event. So really, really useful. Okay, I will pause there for questions. And Cedric? Says that he uses this for notifications on his side.

[2:19:00] Yeah, please let me know how you're liking emit. It is a fairly recent feature. Javier says. I know you don't want to deviate to advanced concepts, but can you give an example? Usage case? For spawn actors? Yeah, I, I definitely will. So really, there isn't much difference between an invoked actor and a spond actor. They're both just actors. It's just the only difference is that an invoked actor is going to be stopped.

[2:20:00] When you leave the state, that's, that's it, that's the only difference. So it started when you enter the state, such as submitting, and it stopped when you leave the state. And just to, just to show this in action, if I say, on, well, actually, we already saw this. So with the timeout, if we give this a really short timeout, then it's going to go to the error state. And because it left this state, this actor, this send feedback actor is going to stop.

[2:20:00] Which means that, even if the promise resolves and it says, Okay, hey, here's the resolved value, it's, it's not going to do anything, uh. Firstly because we're, you know, we're in a different states where that event isn't hand. L. But also because we're actually stopping this actor, with its custom stop logic, when we leave the states, so spawning an actor. And I'll show you what that looks like. Is different because you have to control when it started and when it stopped, and you could start it in an action.

[2:21:00] And this example isn't really set up to do that, but I will show you how to, how to do it. Let's just say I do it here. Actions, there's this spawn child, action creator. And so, you could give it a source. And so that source could be like, from promise, and then you know that could be whatever you want, new promise. Whatever the syntax is for that. Yeah, so yeah, that's how you could spawn a child.

[2:21:00] Oh, it is also expecting something else, it's expecting, like an ID, or, well, actually, this one is expecting input for some reason. But yeah, you could just. Give it input like this. Again, like I said, this example isn't really set up for bonding children, but it's essentially the same thing as invoking a child. And so you like the like these, spawn actors can actually also live in context as well. And you could just pass them around as values.

[2:22:00] If you do want to access them, though, then they are available, so if we go back to the component, they are available in states.. Do whatever the ID of that actor is. So if we go to submitting, we could give this an ID of feedback promise, or whatever you want to call it. And then we'll have state. children.. Feedback promise and then you could actually pass this around so you could say, con um.

[2:23:00] Output equals useSelector taking the feedback promise and then get the s dot the snapshot. output if that exists. So just to show you that's working, let's go all the way here. By the way, this is all being recorded on YouTube, so if you want to watch all of this later, then, please feel free to. So, right now, it's it's not going to show any output because there's, you know, nothing coming from there.

[2:23:00] But if I reload this bad raar submit, something went wrong. Oh, because we said the timeout, so let's pump this back up, reload. Okay, so it should have showed some output, but it did not, maybe because we're not getting output. But you know what, let's go ahead and log date. children. Hopefully this will show it too. Oh, oh, okay. So this is because, it happens super, super quickly, but there is children.

[2:24:00] It just, it's deleted. When you know, when we're no longer in that state, that's right. So, yeah, sorry, I was just trying to show an example, but little bit contrived. I'm gonna. Answer a few questions and then maybe we'll get back to that. So Daniel asks, did you try some, some fun? With fine-tuning LLM to output?

[2:25:00] XState? Like I mentioned before, OpenAI GPT 3.54. It already has extensive knowledge of XAT, so there really is no need to, F tune it. However, in Stately itself, if you go to state. Editor or state. New, you can use. AI to generate machines, and it's free. If you want to generate three free machines, you just enter a prompt and it will generate the state machine for you. And it works for X8, version 4 or version five.

[2:25:00] And so that's. It wasn't so much fine tuning, but rather, uh. We had to massage the data and do prompt chaining, and that prompt chaining actually resembles a state machine itself. But the promp chaining makes sure that, like we, we have different candidates for. Like, generated XState code, and then we, isolate the XState code. We make sure that the code is valid, and then we convert it to a directed graph format that Stately can understand.

[2:26:00] And that's not fine-tuning, but it's the next best thing, which is prompts chaining. So, yeah, Honor says, going back to my question from the start of the webinar, say you have a component that has fallback functionality. If the actor that is spawn, the parent process has not been initialized, like the actor pass Notifier needed to be optional. Okay, so let's say, yeah, that's a, that's a good idea. So, I am going to just to show this, actually, I'm I'm going to make a different component.

[2:26:00] So I'm just going to say this is let's see. Function feedback value, and all we're going to do is, select that value, so useSelector, actor. And this is just going to be s. context. feedback, and then we're going to return feedback valer or that. So, again, this is a contrived example. But if we have feedback value and we pass in the actor over here, you see how we're getting that. This is a completely different component, just reading that actor.

[2:27:00] Now. The original question was, what if this was undefined? Or actually, let's make it optional, and let's say that we didn't pass anything in here. Now this should still. Oh, I, I almost have the latest XState, so PM, PMI React, latest. If you have the latest XState, X8 React, then this should work. Let me see what's happening. Oh so, because this is undefined, this might also be undefined, too. So so now it's just going to work.

[2:28:00] So, yeah, hopefully that answers that question. Where now the actor can? Be optional in you selector. But just keep in mind that when you do that, the snapshot might also be undefined, so you just have to keep that in mind. Another history question if I have a deep history state, am I allowed to put it inside a parallel state? So that a transition to it will make all the child parallel states go back to where they were?

[2:29:00] This means that if the history state itself is one of the parallel states, I. I don't know where else to put it. So this is another feature of statecharts. And just to answer your question quickly, this, this should be in the docs, if it's not, then let me know and I will update it. With your history state, it's going to basically tell you go back to the most recent child that you were at.

[2:29:00] So, step one, step two, step three. With parallel states, you might have children and grandchildren, so you might have a deeper nesting, and so to have a history state, target those deeply nested states. You just do history, oops, if I spell it right, history. By default. Default it's going to be shallow, but if you set it to deep, then it's going to recursively. Go to the most recently visited child or grandchild or descendant child states.

[2:30:00] So that is what you need. History deep, all right? Thomas asks. Do you test your state machines, your actions? Anything else? I do, we do. And, so we do get this question a lot, like, what is the best way to test state machines? And the funny thing is that state machines make it easy to test your logic. But it also makes it unnecessary because a lot of the times you're not like you're, you're testing what XAT ready tests like, if you have a transition like on state A, event E, you end up in state B, you really don't need to test.

[2:30:00] Like, if I'm in state A, and event E happens, then will I be in state B? Like th. Those are things that XState already tests in the library itself. So, you know, it doesn't really make much sense to. However, I'm going to show you, you know, in the XState repository itself, that, you know, we do have you. Know these tests, and also it does give you a good idea of how you could, how you could write your own state machine tests.

[2:31:00] So let me just go to this real quick, all right. So in the X repo, you're going to, just navigate to packages core, and this is if you really, really want to get deep into it. But we have a lot of tests over here and so let's go to, for example, this, deterministic do test.Ts. So in our test, we would have a machine that we create can't code fold in here, and there's a couple of helpers.

[2:31:00] This is available in XState itself. But we have get next snapshot and we have the current machine, the events and a specific state, and we want to make sure it reaches a specific value. However, there's other, let me see if I could find some good ones here. Oh okay. So one of the ways that, you know, we tend to do the tests is first. We define the machine or the actor logic, and then we create an actor from that and we start it.

[2:32:00] And so based on that, we could actually send it events, and so when we send it events, it's where we're going to just assert that the correct thing has been done. So either it ends up in the correct state, or it's, you know, it executes the correct actions. So that's a way that you could test your, you know, your state machines as well. Hopefully that helps, and we'll we'll have more documentation on that.

[2:32:00] I know that we're light on documentation for that, but something that we'll hopefully add soon. All right, let me go back to my VS code is somewhere over here. Sorry, my Chrome is struggling with the 100 tabs I have opened. Okay, all right. So, answering a few more questions, let's see where was I? I'll add this back to the stage. I guess I'll go backwards. Is there any best way to handle React, Router and XState?

[2:33:00] This is, yeah, this is a good question. So in general, and we'll we'll make more detailed guides on this. But in general, what you could do is if you're using a state machine. To define like a step in the process, where the step in the process might not be the initial state every single time. But you might want to do something like read it from query parameters, or like, read it from persistent storage, or something like that.

[2:34:00] Then, what you could do is if you have that persisted state somewhere, you or, sorry, persisted snapshot, then you could just provide that directly inside of. You know, for example, the hook over here, so you could say snapshot, and then, you know, some persistent snapshot. So, in fact, we could just do feedback machine do, restore snapshot, and then, like, this is your snapshot, value so value. Yeah. So this is something that we definitely have to write a guide on, but long story short, and there is actually documentation on this too, but long story short, yes, you can set the machine to a specific state and say you should start at this state.

[2:35:00] And so that way, you could read information from the router or from query parameters or something like that and tell the machine to start at that state. Now, you shouldn't use it to control the state machine and say, Hey, you should be in this state now, you should be in this state, because that's the job at the state machine. But otherwise, yeah, you could just read information externally and turn that into a state that the St machine should be in.

[2:35:00] Let's see how here. Thanks David. That was clarifying, I take. The spawn actor would have persisted inside the machine children for its runtime, independently of the current state machine. Yes, so that's exactly correct if you give a spawned actor an ID and all. This is in the documentation. A little bit more advanced stack state. But then yes, it is going to stay in states.. Children, until you decide to stop it, and then they will remove it from there.

[2:36:00] [Music] uh. When I have nested children, I often provide to them the same stuff and input from top down as props and React. I'd have to see an example of this, but I'm I believe that this is okay. So yeah, all right, so, you know, we're almost at time, and, what I want to? Do now is just answer any other questions that you might have. And also I want to share a few resources quick.

[2:36:00] Okay, so, uh? First of all, you could find a lot of information in the XState repository itself, so there's documentation. There's also the Stately editor. I should actually share my screen, there's also the Stately editor. But something that I briefly mentioned before if you go to state. New, this takes you to our free visual editor. This is a place where you could actually create these state machines visually, so let's say that I wanted to, you know, create a new machine.

[2:37:00] We could just open the starter template, which just gives you a lot of good information on, basically, how to work with this date machine. It does provide a lot of basic starting points for you, so you could just use it as an example, for example, we have these guarded transitions over here, we have a reset action and we have some nested states. And you could also click simulate and click through these, and this will give you a better understanding of how state machines actually work.

[2:37:00] And then you could, you know, do things like add more states, so we could drag over here, that add events, we could add actions, you could even edit these actions in code. Over here. There's, some quick ways to, define custom or common actions like Aign, send to ETC. And then when you're ready, you could click code at the top left and I should really zoom in. And then you could actually export this.

[2:38:00] So you have all this code where you could copy it over and use it directly in your code base. If he wants to now, you could also go the other way around. So if you have an XState example, like I showed you before, you could just, grab, grab it. And it doesn't matter if it's XT, V4, V5. I'm just going to grab a random one over here. You could import it, paste it there and import that XState machine, and this is a very simple machine.

[2:39:00] But this just gives you an idea you could copy paste your code to easily visualize, visualize your machine, so. Here's some more example machines I made. There's also a lot of other features too. So, for example, you could, you could use AI and actually generate a, a nice little summary of your machine. Just so, you know, people could understand how the machine works, what it's for. And there's also test generation, so we could generate test paths, which actually works pretty fast.

[2:39:00] So, and this is using XD test behind the scenes, which is a subject of a whole other workshop, um. But this will actually generate, just test code that you could use so that you could, fully test your state machines and transitions, which is really, really useful for endtoend tests. In fact, most of the generated tests do not use XState at all. So you could even just copy and paste this and, and use it directly in your test code, so it's really useful for authoring tests.

[2:40:00] But yeah, what you could also do is you could export to things like JSON if you're consuming this state machine in something other than XState. Or even things like Mermaid, which sometimes works, Mermaid is weird with its syntax, so it might not always work. It might work for simpler examples, let's see. Nope, that's why. And beta, but yeah, and you could use it in X8, or, sorry, in X8 version five and X8 version 4.

[2:40:00] And things like that. So, yeah. We also have a lot of documentation, so basically everything I talked about today and more is in our documentation. So I really encourage you to check it out. If you're coming from X8 version 4, then we have a an extensive guide on going from X8 4 to X8 version 5.

[2:41:00] You know, with examples, too. So it should make the migration process pretty easy. By the way. This seems long because it's going through every possible thing you could do in XState. If you have simple machines, then the migration process is actually very, very quick. Again, there's a lot of examples. We even have cheat sheets and basically all the docs you could want for anything that you could do. An next datat? So, yeah.

[2:41:00] Our Discord community is at discord..gg. Exat. I'm always there answering questions, and, yeah, thank you, so. Much for joining this webinar. If you have any question, questions or comments, then please feel free to leave them in the comments of wherever you're viewing this on Twitter, YouTube, or even Streamyard. And, yeah, join us in our Discord come chat with us, and I'm always looking forward to hearing your suggestions and feedback, so please let me know.

[2:42:00] Thank you all very much for joining me.
