David Khourshid

Webinar: Create app logic with XState V5

Webinar at Stately webinar, 2023. 1:30:49 long, 7.2K views on YouTube. With Gavin Bauman. Topics: xstate, actor model, forms & ux.

Watch on YouTube (Stately)

What is this talk about?

Join us for an introduction to XState V5 with David Khourshid and Gavin Bauman. (From the video description.)

“We have prompts, and if we look back at the feedback form, we could call this state the prompt states.”

“The reason is because the state machine has that logic, so you don't have to rely on the logic being spread out in your UI, it is contained within the state machine.”

From the opening of the talk.

Key takeaways

  1. Keep in mind, this is an XState version 5 beta webinar, so we're going to be learning the basics of XState version 5. 1:00
  2. We just want to import that directly from XState and you pass your machine into that, so we're going to pass the feedback machine directly into that. 8:00
  3. We have prompts, and if we look back at the feedback form, we could call this state the prompt states. 13:00
  4. What this means is that at any time I could go to this closed state, doesn't matter if I'm here, I could go closed close. 22:00
  5. The reason is because the state machine has that logic, so you don't have to rely on the logic being spread out in your UI, it is contained within the state machine. 29:00
  6. We have this machine, but we need to actually make that a live store, so con actor equals, create actor machine, and we could also start here. 1:11:00

Quoted from the transcript.

Full transcript

From YouTube auto-captions. Punctuation and capitals were restored automatically. Technical terms were normalized; some errors remain. 14,868 words.

0:00 Introduction

All right, hello everyone. My name is David Ked. I am the Stately founder. I was going to say I'm the state Leia founder. Got my words mixed up. Feels like everything's going wrong today, but hopefully this webinar will go just right. And we also have Gavin. If you want to introduce yourself. Yeah, Gavin, my name is. Hi. I'm one of the backend engineers here at Stately. Yeah, so you know what, let's just jump right into it. We've given webinars before on XState version 4, but I felt like we should do a little bit of a refresh. And honestly, we're going to make this quick. Because, XState is not really as hard as you may think to learn. And that's something that I'm going to try to prove to you. And yeah, so first of all, we work at Stately, and Stately is, basically a startup. Where you could make executable diagrams.

And so those diagrams just happen to be state machines and statecharts. And these diagrams have a lot of benefits. You could use these diagrams to represent flows, whether in your front end or back end. And it's a really nice way of just visualizing it and having a shared language and a common source of truth. For the entire team to get on board and understand what the heck is going on in your application. So that's the company we work at. I don't know if you want to say a few more words on that. I, yeah, I mean, you nailed it, definitely. The idea behind, Stately, is to build processing flows, whether they be front end or backend, or, honestly, just business processes. That anyone on the team, regardless of their discipline, can look at and understand. Yeah, so let me real quick show you what we're going to be building today.

And keep in mind, this is an XState version 5 beta webinar, so we're going to be learning the basics of XState version 5. So that you could get up and running. Now, this is sort of what we're going to be building, and if you've seen our previous webinars, you might be familiar with this. This is just a feedback form which could go through various dates. This right here is built in React, however we are going to be. Doing this in vanilla, not exactly vanilla, but it's going to be typescripts. So, we aren't going to be doing the React part. But I will show you how you could take the machine logic that you built and integrate it with Frameworks such as React, and I think we'll stick with React. We have adapters for Frameworks like, View. Felt solid. I'm blanking on the others, but yeah, uh. And if you haven't seen this before, this is a very simple thing that you might, you know, want to build in the front end, which is a multi-step form.

And in this case, this is for, just filling out some feedback. So, for example, if you say that your experience was good, it says thanks for your feedback, you could close it, and we could also provide more feedback. If you say bad, then you have to tell it, you know what you could do, do better, or you could go back. But if you say, you know what, everything went wrong, which I know, you could barely see that, and I apologize for that. But you see the submit button sort of disables and enables when it is valid, and you can send that. And then it says, thanks for your feedback and shows everything went wrong, which hopefully nothing will go wrong today. But again, we'll see. So we're going to be building out the logic for this form and showing you how you could use XState to, to manage state like that. Yeah, yeah. I think multi-step Farms are great examples.

Because even though they're these, super simple things that we think of when we use them online, they can be deceptively complex. Especially as the farm grows right. So there's, you know, obviously, how was your experience? That's like the very beginning of a of a decision tree right there. You have to worry about things like, Oh, hey. Only allow this submit button to be available when the text field is highlighted. You know? So there's state there that we have to be concerned about, and there's carrying along context as we go through the form, right?

Play from 0:00

4:00 Let's say that we had a feedback. event

You know, after I put in like details and things like that, maybe I don't want to hit the server up immediately, maybe I do want to, um. Carry some things along with me until that final submission process. So just wanted to give you some Credence as to why we're, why we're doing a forum. Yeah, and yeah. State machines and statecharts are one of those things where it's like, you don't think you need one. Until it's too late, until you get to that point where it's like, wow. My application logic got really complex and I'm not sure what exactly happened. But also, just with any technology, it is possible to write some, hairy spaghetti code no matter what you use, even in state machines and statecharts. So, yeah, that. That's why we're also going to be talking about best practices here, and we are also going to be answering questions.

This is a live webinar. So if you have any questions, Gavin's going to help me feel the questions and we're going to answer them as best as we can. So, yeah, we're starting from a completely blank slate over here. I'm using stack blits. You could use code, Sandbox, your local Dev environments, whatever you want to use. And for this example, I've already installed it, but you will want to MPM install XState at beta. This is version five. And yeah, so hopefully that's big enough I could zoom in a little bit over here. And yeah. So this is the pretty much the only import that we're going to be using for this webinar. And we are going to start with, well, creating a machine, so imports creates machine from XState. Now, first of all, what is a machine? In XDay terms? So if you've used Redux before or VX or something similar like that, even in React, if you've used, the used reducer hook or whatever else.

I think there's NGRX and Angular. And whatever spelt and solid has, uh. But a machine is basically that thing that defines the logic for your store. In X8, we call those stores actors. But you could basically think of create machine as a blueprint. It is that thing that tells you what's going to happen when it receives an event. And so just to demonstrate this, I'm just going to make a very simple machine con. We'll call this Feb. back machine and we're going. To create machine, and, you just give an ID just to make it look nice. And also let's add some contact. So we're not going to be talking about states or anything just yet. I just want to demonstrate how this is essentially like a container, or like a way of defining your logic. And so the initial feedback will be an empty string, so then the question becomes, how do we actually update this feedback?

So, in XState, we have on, and this is where you define your transitions. So, for example, we could have, let's just call this feedback. update. Now, you could call this whatever you want, you know, you could even just call it. Change doesn't matter, these are your events. So basically, when this feedback. update event happens, then the machine response to that. And so over here, we're just going to have actions and then we're going to import. One more thing from X8, which is assign is an action creator that lets you well update context and assign values to context. So if I wanted to assign something to feedback, you know, I'll just call this updated. And, this is basically our logic. Let's go ahead and create an actor and just show you what this actually looks like, so const. Feedback actor equals create actor. Oops. For some reason, Stack Litz prefers the very verbose imports.

But we just want to import that directly from XState and you pass your machine into that, so we're going to pass the feedback machine directly into that. Now again, if you're familiar with Redux or something similar, then this is going to be your store basically. So again, in X8, we call these actors in anywhere else you would basically call it stores. It's a little bit different. Actors are sort of like a more powerful store, but essentially it's the same thing. So we could just like you could subscribe to a store, you could subscribe to an actor, so feedback, actor. subscribe. And we call what you subscribe to the snapshot, so you could think of the snapshot as basically the states of the actor. So I'm just going to console.log the snapshot and see what we get from that and we are going to, well, we have to start. It okay, and that's pretty much it in 23 lines.

This is your, basic state machine, and you could see that right? When we started, we get this state object. And over here, the important part is this context. You could see that feedback is an empty string, and so let's change that. How do we actually change? What the state of the machine is? Or, sorry, the state of the actor? Remember, the machine is the blueprints like a function, and the actor creates an instance of that, just like a store. So we could send events to do that, and so I'm going to send an event with type feedback. update and I'm going to give it. Well, I'm just going to send that event and see what happens. Okay, now, you see, we have a second state over here and the context is feedback updated. So the cool thing about events is that you could actually pass in, you, you could pass in payload to them.

So we might say, you know. Feedback, this is great, and hopefully you think it's great too, and we could use that feedback inside here. So let's say I want to assign the feedback and context to whatever we got from the events. So, and I'll I'll explain the details of this later. But we could destructure the events from the function, and now we have event, well, return events., feedback. And, just to, completely derail you. DavId like, I'm want to do, um. I just wanted to highlight a question from SAS in the chat, which is where in, their state machine can they save to a MonGod DB instance? And since you're talking about actions right now, I thought it'd be a really good time to jump in. And, give that some, some air. Oh, okay, yeah. So, that's a great question, and that's. One of the benefits of state machines is that you get every single state update or snapshot update from the subscribe function.

So let's say that you wanted to store this in local storage or whatever, we could do, local storage.. Set item. And you just call the state or whatever you want. And then you could JSON. stringify that snapshot if you wanted to save the state, right, but. If you also had an association with a state transition, right, that needed to, you know to say, hey. When this event is received. I need to save something, not necessarily the state, but something to MonGod DB that would be sort of associated with an action based on a transition, correct? Oh so, where in my state machine can I save to a MonGod DV instance? Yeah, so this is called an action. And so we're going to get to actions which are, basically fire and forget effects. We're going to get to that in a little bit. But, this is useful to know that in, in here, you could just, persist this state. And then you could revive it later. And just to give you a preview, the way you revive it is just by, passing in the state here, so, you know, you could.

JSON. Parse, whatever you get from local storage. But right now, that's really valuable. If you need your actor to be long lived, if, for whatever reason you want to plan for, your actor potentially having to be, you know, taken off the Heap. And maybe you need to worry about rehydrating that state down the line, it's really good to be able to save it and then find it later, especially useful for backend workflows. Exactly so you could see here that we had this date, this context over here of an empty string. And then we sent an event with the message this is great, and then that was assigned directly to feedback over there. So this is the way that you can make a simple store, with XState. So you see, you don't actually need to have a nested states or anything, but that is the strength of state machines, so we're going to jump right into that.

All right, so let's get start and let's actually make a state machine. By the way, I'm going to be doing this in code first, and then we're going to be looking at the visual aspect of it. Which I think is one of the true strengths of state machines and statecharts. All right, so we need to start with, some states, and so the first state that we're going to have is a prompt state and so. The states go in this states object, where each of the keys is the states, the state key. So we have prompts, and if we look back at the feedback form, we could call this state the prompt states. When we click bad. We could call this the form states, and then if we go here, we could call this maybe the thanks states. And then we, of course, have a closed states, too. So these are just different states, statuses, modes that your app could be in, and when you send an event, you could transition between those states.

So, yeah, let's go ahead and add a few of these. So we have prompt form, thanks and closed. So those are going to be our main four states right now, and we also have to specify which is our starting state, so which state is our initial state. Is it that just say that it is prompt? Now I'm going to log snapshot again just to show you exactly what's going on. And you could see that the value is now populated with prompts, and so that just shows you that we are on our prompt. States. Now. Notice here, too, that we have a second state. And that's because we sent an event, but it didn't actually do anything, and that's because we got rid of that transition. And so this is actually an important point. The reason that we would have these finite states is because, for example, this feedback. updates event. You might not want it to do anything unless, of course, you're in the form state. So obviously, you shouldn't be able to send feedback in the thanks or the close dates, or even the prompts.

State at first, and so that is a very, very useful mathematical quality of state machines. Where it basically makes impossible, transitions impossible, and you consequently, impossible states impossible. Where you know that only in the state where a transition is defined, will it actually have an effect? Yeah, so, and that really helps, in the if you zoom out a little bit. It really helps prevent things like the need to build overly defensive programming. Gymnastics into your code, right? Because you do have that, that sort of Peace of mind, knowing that, yeah, I'll never get. From prompt to closed without first having gone through, form, and thanks, or thanks, excuse me, right? Yeah. So now how do we actually transition between those states? You might have been curious when we did our zero state machine as a store example. You might be wondering, why did we put a sign in actions like, why does that have to be an object?

Why does the sign have to be in there? Instead of just that? Being a function which updates context, and that's because transitions can do a lot more, of course, than update context. So, for example, in prompt, we might have a feedback dos good events, and so that might take us to the thanks states. So that way, if we send feedback. good, now we'll see that we went from prompt to thanks. Now let's say that we had a feedback. event. We might want that to go somewhere else, so feedback. bad. We might want this to go to the form states, and then, you know, in the form state. We might change our mind. We might say, you know what? Maybe this wasn't as bad as I thought. So we might want to go back and then we're back to prompt. So it's actually pretty simple. If you get over the fact that this is one big config object, it.

It's pretty simple to, just, see how you could use this to define flows and flows that might not even be linear. So these, you know, you could go back, you could go forward, you might jump ahead. So it's not just step one, two, three, four, but it's a little bit more complex than that. And so that's where that's where I think state machines really shine. So let's, fill in a few more. Oh, sorry, go ahead. I was just saying, plus one, all right, okay, so now we have a few more. You see that it wents to prompt, and then it wents to thanks. Let me put a new line here, just because, oops, that made it even worse. Okay, do log, so, yeah, stack Blitz does not really. Let us set the font size here. So I had to use some, some CSS trickery to get that to actually be legible.

So let's say I go to feedback.. Bad. Now you could see that it goes from prompt to form, and, also we could, let's say that we want to close it as well. When we get to thanks, so okay, let's say that we're going to the form and we. We submit some data. Now we can see that it goes from prompt to form to thanks, and then in thanks, we might want to close it. So on close, target, closed. Now I accidentally did something. It's sort of a short hand and you, if you want to use it, that's fine, but if you only have a target, then you only need to specify the string. But you know, that's just if you're like me, you want to be lazy. Otherwise, if you want to keep things consistent, then just make the transition. A an object like this can't hurt.

Sorry, I said, it can't hurt. Yeah, no, no, Absolut absolutely not. Um. And, of course, because state machines do not have to be a cyclic, we could say, for example, on restart, we're going to go back promt. So, yeah. So let's say that we have some bad feedback we submit and then we close it, so we're on the thanks date. Then we close it, and then, you know, from close date, we want to actually restart it. Okay, so now, you're going to see, we go from prompts to form, to than to closed, and then back to prompt. Now I'm actually a bit sick of seeing all this text. So what I'm going to do is we're going to actually visualize this. I'm going to copy this, create machine code, and you could go to states. new, and, you have to log in to do this, it's free, don't worry. And so if you copy paste this, then you'll see our state machine.

So let me zoom out a little bit and so we could see that this is a state machine. That's generated from the exact code that we wrote. So if I were to simulate this, you could see, let me zoom in a bit, all right, cool, so you could see that. We start on the prompt state, and there's two possible events that could happen feedback. good or feedback. bad when we. Transition or sorry, when the machine receives the feedback. bad event. We go to the form states and from here we could go back to the prompt states. We. We could also submit from here, so let's click submit and then we go to the thanks date. So this makes it actually pretty clear to see the flow of, you know, everything that can happen. And this really helps you just model the logic better, just by saying, okay, maybe this transition should be there, or maybe this shouldn't be there.

Oh, we had a question in the chat over here could you past a machine here? Missed a couple states? I'm going to be sharing this link after the webinar, by the way, so you're going to be able to see everything. No worries, yeah. So K, can you see any potential ways we could improve this? GAVIN I would. If I were looking. I'm sorry, I was responding to feedback. No worries, I'm sorry. Well, so I, I'll tell you one way. Have you ever had a feedback form that sort of forced you to put some feedback? Like? It's like, Hey, you cannot exit this? Yeah, you can't exit this, and also you can't go back and change your mind exactly, so take a look at this. We have this close event, which I'll just Mark in red over here. And it looks like you can only really go here from this state.

So that's a bit of a problem. Again, let me assume in a bit, what if I wanted to say no to drugs? Halfway through? Exactly? So what we could do instead is we could say, hey, I want this to happen in, like, pretty much anywhere. So what this means is that at any time I could go to this closed state, doesn't matter if I'm here, I could go closed close. And so basically, this is a transition to like, or from anywhere. And so that's one of the benefits of using these hierarchical state machines, or, in other words, statecharts. And we could use the same technique that we used, at the very beginning of this webinar, which is just, say, on close. And then we could just go to target dot closed, so this dot means go target one. Of your children, so that's what you know. Dots closed. So that's what that sort of signifies.

And so now, if I just put this close events pretty much anywhere else, and you could see that we go to the closed state over there. Whereas if we didn't have that, then, of course, going to close would still keep you on the form, or, sorry, sending the close event will still keep you on the form. So, yeah, and let's see, ben Patton says. So many cancellation forms will not allow you to proceed and canceling without giving a reason that is I canceling. All right, gonna take a minute and answer some questions here too. Hi David, great stuff. Quick question, thank you. By the way, using reacts from the initial state, say we have an event that targets another states and fire an action that will update the context. How many rerenders will occur? One or two? The answer is one. And that is because both transitioning the states and applying those assigned actions happen in the same step.

So don't worry, you will only get one rerender over there. All right, so we have our basic state machine. Let's actually, you know, just make this a little bit more robust and just get to some more features in XAT. So when we're in the form right now, you could submit, you could go back, but let's say that you actually wanted to, you know, keep track of the things that you're typing in the form. So I'm going to add a feedback, update, events. And just like we did at the beginning, it's going to be actions, and it's going to be an assign action. And so, we are going to assign to our context. We have. Over here, we're going to say the feedback is going to be, let's just say events. value. So I am going to submit now, or, sorry, I'm going to obviously send some feedback, and let's do it over here, feedback. update and the value.

This is sort of okay, I guess, I don't know. So we see that we're still in the form state, so let me actually log the context over here. And now you could see that once we send that event, we get the feedback updated with this. Is sort of okay, I guess. And then we go to this thanks state over here. Now let's say that we actually want to only submit, like you could see in the original form, only submit if, you know, if we actually can, or like if the user actually provides feedback. So right now, you know, that's, let's see, let's reload that. So, you see, we cannot submit because, no feedback was provided. And so what we could do is we could use a guarded transition to do that. And so I think this is one of the coolest parts of, you know, using state machines and statecharts is being able to model this. Because I'm going to show you a really cool feature. That results.

Because of this, I could put a guard over here. And this, by the way, is different from version four. In version four, this was called cond and now this is called guard, because it's a guarded transition. That's part of our effort of consolidating terminology. So, we're updating the feedback value in context, and we just want to make sure that context. feedback. length is greater than zero. And if it is, we go to thank thanks. So now let's try that out, get rid of this. And now you can see, we are still on form. And that is because this value is invalid, or, sorry, it's not invalid. It's just the guard doesn't pass. So this transition will not be taken. So how do we fix that? How do we fix that? We provide feedback. Yeah, there, there's a lot of activity in here, let's see. Yeah, I'm catching up.

I'm sorry. Yeah, feel free to interrupt me. And, you know, just pull up what you know. Anyone says? Okay, no worries, all right. So, I was going to say that there's a good benefit of doing this, and so let me just show that to you real quick. Oh, okay, yeah, so there we go. Something that's really common is that you might want to disable certain form elements if, you know, for example, if it's invalid or not valid yet or something. And so because we have this very declarative and deterministic representation of your state logic, we could do things like this. So in this button. I have, disabled equals, not state. can and this event over here type submit. And so this is, in my opinion, a lot more. Rob then, you know, having to do something like, disabled equals, what would it be like? States. context. feedback. length is, I don't know how it could be less than zero, but, you know, less than or equal to zero.

You haven't tried? You haven't tried me as an end user for your survey? Yeah. And so the reason is because the logic for this now lives completely in the state machine. So let's say that in the future, you want to change this logic or this rule. So that, the user must provide feedback that's minimum 10 characters or something like that. All of a sudden, your UI is going to be broken. Because now we could submit it with nine characters or two characters, like okay, or something like that. So this just, says, disable this button if you're not able to submit. And so if the logic says, Hey, submitting shouldn't do anything thing, then, you know, then it should be disabled. So I like that a lot. And also here's another benefit of state machines 2. If I get rid of this disabled attribute and you see, it's not disabled anymore. But I don't type anything in here. I'm going to press the submit button, which it's, it's definitely going to trigger this, so there's nothing guarding against sending that submit event.

But you could see, I promise you, I'm clicking ferociously on this button, nothing is happening. And the reason is because the state machine has that logic, so you don't have to rely on the logic being spread out in your UI, it is contained within the state machine. So now I could be sure that regardless of if that button is disabled or not, the logic is going to be correct. Now. Obviously, it's very good to have that disabled state. So that users know, okay, something is wrong. And you give them some sort of visual indication that they probably need to do something about it. Yeah, let's see Andrew. No says. Can you return an error if a guard is triggered? Oh, yeah, that's a that. That's a really great idea. So, in terms of modeling it, you? Might want to model, for example, an error and we'll just make this null. And so, actually, I'm really glad you asked that, because, all right, let's say that this guard does not pass.

What you could do is you could have another transition. So it's sort of like a if then or sorry, if else, if else, if else if, sort of thing. So you could say, okay, if this transition is not going to be taken, then I just want to assign. Is it error? Your feedback is too short. Okay, so of course there's null over here because nothing's actually wrong. But if I get rid of this now, we have this error that says your feedback is too short. So again, the way this works is that it's trying to take this transition and it's unable to do so. So instead, it's just going to take this transition and notice that there's no target. So because there's no target, it's not going to go anywhere, it's just going to stay on the same state and still there. All right, glad you like that. Okay, so let's see, back submits. We have, filling out data we have.

Oh yeah, so these are actions, and so far we've only covered the assign action, but you could, of course, do other actions as well. So, I'll I'll give you a demonstration of that. Let's say that you want to, oh okay. So so we have close on here. Let's say that we want to. Just, I don't know, do something. Send analytics log that something was closed so we could have, this is called an inline action and I'm just going to console.log closed. So, right, well, we have to actually close it, so let me just that, and then we have close. Well, it doesn't help if the, if the console is the exact same as the state name, so you could see over here. It says loging closed. And you also might be wondering if it's plural. You know, can we have more than one? And the answer is yes. So you could have multiple actions here, so we could say logging closed and maybe logging something else.

It's like that, and you also have access to context, event, and a few. Other things, too. So I'll just log, the event was, and we'll just pass in the event.. Type Oh, logging Clos, the event was close, or the event was close. Sorry, the words sound the same, or they're spelled the same, but yeah, so the point is you could have multiple actions, and so an action, by the way, is a fire and forget effect. That means that this action does not really care about, or sorry, the state machine doesn't really care about the results of the action.

Play from 4:00

34:00 Meaning if whatever the task you're running can operate without that…

So if you really wanted this to be a sync, you could totally do that, but it's not really going to do anything. You know it, you, you might as well, just, you know. Just call the promise directly over here, because the state machine is not going to wait for anything to happen over there. Now, sort of a pro tip over here. If you did do something async over here, like, await, you know, promise or something, I don't know, uh. And then Res 42, then oops, this, any keyword or anything, so const. Result equals, you know, result 42. I'm just winging this right now. It's okay. In X8 version 5, there is a new, a new thing that comes in this object over here, which is self. So what you could do is, you could, you know, you could technically just call a promise over here and type self. send. And then just send it whatever you want, so that's something you could do.

Actions are pretty powerful. I'll pause there for a minute. Yeah, I'm catching up on. The array of actions is amazing, that's awesome. This might be a bit outside the scope of this session, but SAS is asking about, pretty much like, concurrency, right? So if a machine manager, spawns a machine, that machine needs to save off a database task, should it have a parent manager or should the spawn child machine handle it? And I really think that's a context related question. Meaning if whatever the task you're running can operate without that machine, without that database save task needing to have been done, you know, in order, then, yes, you could totally have a spawn machine or an actor. Handle that safe process while. Your parent machine does other things. You could also have, like, you know, the notion of parallel states, right? So you can have things happening at the same time if you needed it to.

Again, I don't want to derail David. But, it was easier for me to answer it live than, type. I'm trying to catch up. No, it's all good. And so this is the kind of thing that state machines make you think about. Because, and we're going to get into actors real soon over here. Basically, the question is about, like, which actor should really take care of that logic, and that's that's up to you. Yeah, I mean, it's sort of like the same thing as, you know, microservice orchestration patterns, yeah, versus the, full fat monolith. Yeah, um. The important part, I think, from XAT perspective, is that we do support it. So if it's control flow that you want to, you want to, model, it can be done with the use of statecharts and state machines. Uh. Specifically that scenario, though, it's probably going to be a little bit complex.

You're probably going to have hierarchy, and you're probably going to have to De with, you know, parallel states, oh, there's Al always a bad way to do anything. Yeah, yeah, so, by the way, and I know that we're jumping ahead a little bit here. But so XState allows you to model actors, too. So basically, just think of the things that state machines create, or, you know, create. Actor would create an actor, which is a store, an actor could create another actor, and those actors could create other actors as well. And so once you learn that, and we're going to learn it real quick over here, the question becomes, how much should I split apart my logic into different actors? And so the analogy that I like to make here is think of it like a workplace. Where, let's say that you have a bunch of tasks to do. And so it's always a question of, should I try to do all of these tasks myself?

Sometimes you can, and sometimes that might not be the best idea, so what you do, you delegate it, you say, Hey, can you please help me out with? With this task, which might be one of many tasks you have, and so there's a tradeoff in that. The good news is that you yourself have to do less work because you're handing it off to someone else to do. The tricky part of that is that now you have to actually communicate with that person. So that task, which would have been synchronous if you know you were doing it yourself, now becomes async. Like, if I hand off a task to Gavin, then I have to just rely on Gavin. Messaging me back, saying like, Hey, this was done, or me communicating with them and doing all of that. So it becomes a tradeoff, like, should you try to do everything yourself, or should you delegate and pay the what I call the communication cost?

The message passing cost? Which, you know, might be fine in certain situations. And that's also why, you know why microservice architectures are a thing? You know why? Your infrastructure diagrams look like, I don't know. Spaghetti, right, right, yeah, or why the actor model exists, right? So, you know, it's, it's meant to deal with that complexity and that concurrency.

Play from 34:00

39:00 Instead of just being in the form state…

We have one more that I wanted to catch, on stream, and I think this might be a simple one to actually model. David. So, uh? Andre asked. Sorry, I keep interrupting. No, you're fine, uh. Can we apply something like a ZOD scheme of validation to the form during submit? I think that's a really good one. So, let's where. Where is that? Could you put that on the screen? Yeah, actually, I have no idea how. I think, Oh, really. Yep, no, it's not doing it for me. I'm sorry. It's a few up though. Okaying for find it real quick. Okay, yes, there we go. Can we apply something like a ZOD schema to the form? During submit? I mean, yeah, you, you absolutely can, and so the question becomes where you want to do it. So you could do it like in the UI itself, like over there, but I would honestly rather do it in the machine.

And so, if you're unfamiliar with sod, sod is a way of having runtime and type safe values at the same time. It's. Really useful. I don't know you have a better way of explaining it. Gavin, you've been working with it more than me. No, no, you nailed it. Yeah, so runtime safe types, yeah, in a way, and so, yeah. So that's why, you know, you could have a submit in here, you could apply your ZOD schema, and you know, so you. You could also go to this validating state where you, you know, model that and say, Okay, we're going to validate it. Save the validation errors to context, and then based on those validation errors, you know, you might, go to, this error states. Which, you know, I'll just model real quick over here. But yeah, so you could definitely use Zod, within that. And I think that's a good pattern that we should really make, make an example of.

Yeah, I think so, too. I think Z is awesome, and sort of, makes TypeScript complete in that way, right? Like TypeScript gives you, you know, compilation level, type validation, and Zod. It's the other half. Right, right. Yeah, all right. So let's actually talk about actors now, so, actors are basic. Sorry. First, a little bit of terminology, what we created here. This is known as actor logic, so this is the logic behind your actor. It's not actually the instance, right? So this just tells you this is what your initial context is going to look like. And so these when you create an actor, these are the actor reps. They're references to an actor, and that reference is something that you could pass around like a reference. Send events to and subscribe to. But state machines aren't the only types of actors that you could create. So let's do a little bit of an example, let's see form on, feedback., update, etc.

Etc. So what I want to do, and this gets into child states and actors at the same time. And actually, I'll show you over here, because I think it's a little bit better to model it right here. Let's say that we also want to model that. When you're in the form state, you could be in a couple of other child states as well, so I could be in some sort of editing state. And then when I submit, I could be in some submitting states too, and so now from the submitting states, I could, you know, be done with that. So let's just call it done. And then I go to the thing. States, so these are known as child states. And the way they work is that when you transition, first of all, when you transition to a parent state, you also immediately transition to the initial child state.

So we're in the form state, but we're also in the form. editing state. So that's this nested state over here. And then when we transition, we're still in the form states, but we're also in its child submitting state. And so this allows you, to, yeah, to just represent more complex log. And this is one of the biggest benefits of statecharts, and yes, you do hierarchical states. Literally was typing the response that was gonna sound so cool, and you just ruined it. DavId Geez kidding, kidding, sorry, sorry, uh. And yeah. By the way, you could go, I mean, don't don't go too deep, but like, you could obviously go infinitely deep. So you could have like, states within states, within states. You know. And in the future, we're going to be adding updates to the studio. Where you could actually collapse these, expand these and just have a better way of viewing them in general. So yeah, this is what we're going to be modeling.

And let me show you how we would do that in code, so we would need an initial state. And actually, you already know how to do it, because it's a copy paste of what you did right up here. It's a recursive data structure, so initial might be editing and then we have two states editing and submitting. And so now what I could do is I could take these transitions, and I'm going to just copy paste it into editing. What this says is that this feedback. update event can only happen in the form editing state, it can't happen in another states. But we might want something like back to actually, you know, be in any state. In the form, which might be weird if you're submitting the form, but you know, that's okay. This is just for demonstration purposes and, of course, submit. You would want to go to the submitting states now, so now you could see that.

Instead of just being in the form state, we're in the form editing state. And this is how XState represents, these nested states is via an object, so, let's see form submitting when you submit it. Oh, yeah, am I? Yep, I'm logging the context. That's why it's showing. And then eventually we'll go to the closed states and then we go back to the prompt states. Okay, so I promised you I would talk about actors. And so let's say that you want this to actually call or to actually do a fetch request, right? So this would be invoking a promis actor, and so the way we do that, we invoke in our source. We have this handy from promise helper over here. And now we could just, just, you know, pass it a, a promise. And so I'm just going to do, await, promise. r, or sorry, new promise.

Solve and set timeouts, and we're just going to resolve. I know something 200, I have no idea, after a second. And so now that's pretty much all the code that you need, this is going. This is the actor. Logic for a promise, so, you know, if you didn't want to represent your logic with a state machine? You have a lot of options to choose from. You could use promises, observables, transition functions, call backs, and you could even make your own. And so, in this invoke object undone, we're just going to, so here's an interesting thing. You could see that we're sort of crossing boundaries over here, which is a little bit awkward. Because, really, you should be targeting only siblings, or, you could also target like children of siblings, but targeting parents is a little bit weird. It's not impossible to do, and I'll show you exactly how you could do that. But, you know, it's a little bit of a modeling smell.

So I'm just going to give this an ID of things. So that we could target it from anywhere. And you just like in HTML, you could just, or JavaScript. DOM, whatever it is, you could target that, that ID, so we have target. Thanks, okay so. Now let's see what happens. So we start in the editing state and then from here we get to submitting. And oh yeah, so we I actually want to not send these so that we could see what happens over here. So you see, it submits and then after a second it goes to thanks. And that just shows that our promise. Actor worked now again, you could invoke many things over here.

Play from 39:00

48:00 By the way, in version five…

This could also be another machine if you want, so you could definitely do that. And yeah, let's see if there are any questions about that. Yes, I just got a really good suggestion, which is to add in some, examples of, using XState with Playwright. So I was, logging that in our little feedback portal. We've got going up here, uh. Any way to visualize spawned actor, spawn machine actors inside, oh, inside the VS code versus the studio? When I use the plugin, I can only, see, two tables individually using no.. JS. So I think I think what, Saras is getting at is, can he see like, a live instance of a spawned actor? From the VS code extension? I don't believe you can do that from the VS code extension. Just yet. Am I incorrect? David right? No, not just yet. Yeah, we do have the existing, fact, yeah, we do have the existing, Stately visualizer, which looks like this.

And this is something that we're in the process of porting over to, you know, to the studio itself. If it takes a while, so this is loading Monaco, which is why it might take a little bit to load. Yeah, or maybe it's completely broken now. In the ViZ, you actually can see, all the actors that you have defined in your, in your machine. Which is really cool. But, uh. S Ross, I think you're living my best life right now. Which is, trying to, Puppeteer several back-end processes, all attached to different, spawn actors at the same time. And, you can definitely do that with XState. But being able to visually see it from VS code is something that. I don't want to put my foot in my mouth, but it's it's honestly my pipe dream. To be able to see that, I think it'd be very cool. Oh, and thank you, Martin for answering this one.

Andre asks. In V4, it was possible to define services and actions as strings and then pass them to the instance. Is that still possible in V5? Yes, it is. So. By the way, in version five, since we're focused on consolidating terminology, those services are instead called actors, so we're not going to use the term services anymore, just to eliminate confusion. So let's call this, source. Submit feedback, so notice I'm changing it to a string. And now either in the second argument, so you could provide this in the second argument, like actors, submit feedback. And then you could just paste that there, you're going to get the same result, so after a second you get that. Maybe that happens a little too quickly, so I'll just do a two seconds, one, two, and then you have that. Thanks state. Or if you want to provide that, later, you could say., provide, and then, pass that in.

Play from 48:00

51:00 I have this as some feedback

So this is good if you have the same machine, but you want to use it in different ways throughout your application. So, yeah, other things you could do, too with regard to that. We could say like, let's call this C. Um. Feedback valid, and then we could just say feedback valid. We could pass that in just like that, uh. And so this is going to be the same sort of thing. So that if we send invalid feedback, then we have that error. Your feedback is too short. Forgot that we add that error, but that's pretty handy, actually. So yeah, that's nice. Better I got. I got one more question for you, David, that, I think, is a really good one. A Devon wild. My brain says, a wild Devon, but it's a Devon wild says. It's so well thought out. By default, uh. Should we say that access to global states is private? So you want to talk about the concept of global states in the U.M. Context of that state? I think, what a Devon wild.

What he might be referring to is this over here? Right, correct me if I'm wrong, like, just going beyond. The boundary of the leaving one actor going back up. So, yeah, I. I' actually like to briefly talk about how we would better model this in a way that, is a lot more scalable to your application logic. So instead of doing this, let's say that, oh yeah, let's actually invoke something here, so we're going to invoke and let's say that this is, submit feedback, or whatever I called it, it's probably wrong. And this has just a default ID, so I'm just going to give it another ID. I'll just name it the same thing because I'm lazy, um. So we might end up in this submitted state when that's done. Now, what I could do is I could say that this is a final state. And by the way, in the code, a final state is marked by putting type final. That's all you have to do.

So now, what I could do instead is I could make a transition from the parents and it goes to thanks. And this can be a states done event. So what this means is, I don't care what the child states are doing, which child state you're in. Once one of them reaches their final state, and once this state is done, essentially, then transition to the thanks states. And so what's good about this is, let's say that you're submitting, but you know, oh, that's an error. But let's say we have this as a normal event, like cancel, and let's say that we want to model that. You know, we actually cancel this, but this canceled should be a final state where it's like, Hey, if it's canceled, then that's that. Now. What's cool about this is zoed out way too much. So if I simulate when we go to feedback.. Bad notice that when I go to done. It's going to go to this final states, so let me show that over here real quick, it's going to go to this final state.

And then it transitions to thanks, because it took this onone transition, now if we go back and we go to cancel instead, this is also a final state. So it's still going to take that onone transition and take us to thanks. So now the I guess you could sort of call it separation of concerns, where? All the logic within form is like, Hey, I will tell you when I'm done, don't worry about which states you know you're coming from. ETC. So, yeah, I would say that this is a cleaner way to model that, yeah, and in that case, FOR's state is private in and unto itself. And it, aderes a bit better to what the actor model sort of embodies, which is that every individual actor has its own state. You know? Like, even a parent actor can't mutate the state of a child, right? You can obviously communicate with the child and send it events and things, and those events can mutate that internal state, right?

But the only entity respons responsible for that is the actual actor itself. Okay, so now I have this as some feedback. And then you could see that we eventually gets to the than states over there. So we did it, yes, we did it all right. So, I mean, there's there's a lot more to talk about. But, you know, this webinar might get a little bit long. And this hopefully is enough to get you started. With all of this, let's see, what am I leaving out? Honestly, like to just get started with this. This is pretty much, the basics of what you need to, you know, basically make a form like this. And, I, I want to briefly talk about. Like, how you would, basically use this within an application, and also how you would add types and learn more about just integrating this within other Frameworks. So talking about types real quick, instead of putting them in the generic.

The big change in version five is that, you know, let me just inline this real quick, just to it a little simpler. The way that you would do it in version five is that there's a types property and the types are sort of inline like this, which might be a little bit weird, but it, you know, trust me, it makes things a lot easier. So I could say the context is an object that has the feedback property, which is a string. And and then here's all of my possible events feedback. good bad update, submit, close back and restart now. The benefits that this has. Is, if you, misspell something like Feedb, then, you know, it will tell you like, Hey, this is, you know, this is not in events, right? Yeah, and also if you a lovely creature. Comfort. Yes, you have Foodb over here and it's like, Hey, this is not the correct value.

So, and of course, you have your auto complet over here, which is pretty nice. Yes, so you have all that save my fingers. And you do have these contextual events too, so you know that we're going to have event. value over here. But if you do something like, you know, submit, which doesn't have a value, then you don't have, you only have the type, you don't have the value. So, so, yeah, that is how you could add types, and you could also, of course, add types for actors, guards, delays. Pretty much, you know, just all of those different things. Oh yeah, so one other quick thing, which I think that there's a lot of new features in Next8 V5 by the way. This is one of the new ones which I don't think I've gotten a chance to show yet. But let's say that we have, you know, uh. FE feedback, M.t. And so this is context. feedback. length is zero, and so this is going to error because feedback, this feedback valid, doesn't exist.

I'm going to put feedback empty, and obviously you want the opposite of that, you want it to submit. If feedback is not empty, so how do we type that? Let use KN Ah, not feedback empty. And now you, you have guards that you can negate. You, you could even go like deeper with this, you could just be like, and feedback empty. I, I won't get into this too much over here. But you could just have this as an array, and this might be true, you could say, and not feedback empty. So basically, you could build up your logic in a very declarative way over here. This is one of my favorite new features here. Yeah, I didn't want to stop your flow, but I it actually, addresses, I think, pretty directly Patricio's comment and question, which is asking, imagine having several? Guards on a big machine and imagine trying to unravel why your machine, ended up in some state. How can we reduce this complexity?

And the same with using several actors, and I think, you know, just one of the the Creature Comforts. The niceties is having the ability to write your logical operators all in one line. So you can say, hey, well, if it got here, then something about this line isn't working, right?

Play from 51:00

1:00:00 Sequence diagrams are just as important, in my opinion…

Yeah. And also the ability to log out states. I'm sorry, uh. Transitions and events that led you up to that current state is a good way to sort of have an audit log that you can track exactly. And so in XState version five, we this is a PR that's in progress. But we're going to have an inspect API that allows you to ex like inspect exactly those things that Gavin was talking about. And to just see which transitions led to the states. And so this gives you much deeper information than you would have, you know, you, you would have had if you did it. Like with just normal code, because it's doing, it's working at that level of abstraction where you're now talking in terms of states and events and transitions, instead of just code and if statements and async, whatever, and things just happening everywhere.

So yes, yeah. And of course, we're going to, you know, be providing visual tools, that allow you to visualize. Those, I guess, those moments in time where it's like, oh, this event happened, this transition happened, and this state happened. And also communication between actors too, which I'm pretty excited about. Sequence diagrams are just as important, in my opinion, as state machines too. Yeah, where? Where? State machines can diagram the what? I think sequence diagrams. Obviously the word sequence implies it, but it diagrams the when. Right? When do these things get events and in what order are these things received and sent back and things like that? So the ability to use, you know, statecharts to also model state, sequence diagrams is sort of like, you know, it's a chef's kiss to me. Patrick, um? asks. When can we expect X8 version five out of beta? How dare you ask when a Dev is going to be?

Finished Patrick Kid. Our goal is by the end of the year. And so Mati, another core developer working on XState, and he's basically in all of your node modules. He's a TypeScript wizard. He, he actually gave a very specific so answer to this, um. We rely on some Cutting edge parts of TypeScript to the point where TypeScript even uses XState in their testing Suite. Just to make sure they didn't break anything like, that's how that's our, our crazy, our types are, but they're crazy for a good reason. And that's because we're trying to, we're trying to go beyond. Or, like, just go as far as we can with H TypeScript and just provide the best typings possible. And not easy to do with statecharts, but we're trying to make it happen. And so some of the things that we want to do rely on a TypeScript version that's due to be released mid November. So until then we're going to have all the other Integrations, basics in, get the tooling up to date.

And then hopefully when that's released, everything is going to just work out.

Play from 1:00:00

1:03:00 Sure, so we could say actions, and, you know, see…

But our goal is definitely at least a release candidate by the end of the year. So, and in fact, one of our like final sort of breaking changes, which, really doesn't affect. This video at all, was just released today, and that's with snapshots, with actors. And the whole point is just to make everything have a nice, consistent interface. Let's see, Ben says. Love watching all of. Thank you really appreciate that. For testing machines, is there a preferred way of disabling side effects? We're trying to force a machine into specific states and then take snapshots. Yeah, so that's another, you know, great thing about state machines and statecharts is that. And this is why I always encourage, like, when you have side effects, like, actually, let me just go back here. Oh yeah, over here we had this console.log loging closed, which you could. Oh, we have to actually close it. So, let's let's close it, and so let's say that, and that's weird.

Why didn't it? Onsubmit close? Aha. That's why, because I want this to be a GL Global thing, so I'm just going. To move that here, okay, cool, so we see login Clos over here. And so maybe you're testing and you actually don't want this to happen. Maybe this is a more dangerous side effect that's making a network call or just doing something that's potentially destructive. What you could do is, again, parameterizing actions is a good thing to do. So just let's call this log closed, and then in our actions, say log closed, is this function that just logs closed, so it's still going to log closed? However, what you could do if you were in a testing scenario? You could just, you know, yeah, just swap those dependencies out. Yeah, sure, so we could say actions, and, you know, see, this might still do the same thing because we haven't overwritten that, so we could just say log closed and this should do nothing.

Now, you could see, I don't know if you saw that, but that disappeared. So, state machines and statecharts provide you. Or at least in XState, they provide you a way to just mock out anything that might cause a side effect. So you can mock out actions, guards, delays. Actors, things like that, and, yeah. I'd also add not to, underestimate the power of the simulator. I found that I found that it's just been really handy, just visually, to say, okay, well, what happens when I get here? So it's a it's a good step one in testing, it does not replace, you know, automated testing or anything like that.

Play from 1:03:00

1:06:00 You have location, Independence, so you could send an event anywhere…

But it's a good way to sort of eyeball and see. Okay, this is what my happy path looks like. This is, you know, when things aren't supposed to work out, this is what it looks like. Without executing all my actual logic, exactly, exactly, Andre asked, what TypeScript niceties are you working on? I actually don't know the answer to this. Oh yeah, yeah. So, besides the fact that you could add, you know, all of these types, so not just context, events, actions, E.t.c. One thing that we've been dying to do is, strongly type these states, which sounds easier than it actually is. Because, and by states, I mean, like these actual state keys over here, because when you have nested states. That actually gets really, really difficult for TypeScript to do right now. And there's actually a whole bunch of inference that we will get, in future versions of Typ script. It's just not really available yet.

Because, honestly, our goal is that you're writing your state machine and all of the logic in here, or maybe if you're not writing and you're using the editor to generate it. Instead, the idea is that you should not have to specify other things just to get, you know, really nice inferred types for everything that can happen. So basically it's it's inference, inference of these state keys, E.t.C. And maybe more things in the future. Yeah, it's good to know that we're, you know, a lot of our work is, uh. Also having the KnockOn effect of making TypeScript more usable for things outside of Xtape. You know, just in general, the programming language is just better now, which is really exciting. Oh, SAS, and I'm sorry if I'm mispronouncing the name. Is asking, has anyone built a multiplayer live game synchronized with Socket.io with XState? Any examples? Yeah, so if you go to our YouTube channel, which is youTube.com/ AI, we actually did an office hours recently.

This one, the one with the balloon, I would say, go ahead and watch that one from September 1st. Because, this one actually has a lot of, a lot of really cool things that we showed off, including a multiplayer. I think it was an emoji sort of thing. Yeah, it was awesome, yeah, so we were using those DA and party kit, and here's the thing. The main abstractions in Stately and XState are, well, your state machine, of course. But you're actors, and actors can send events to other actors, and so by doing that, it doesn't matter where those actors live. You have location, Independence, so you could send an event anywhere, you could model a websocket connection, or even something local doesn't really matter. And so, yeah, it becomes very possible to create these multiplayer games. And, you know, people have definitely done this before, too. So, yeah, we'll definitely have some more examples of that as we as we get around to making them.

Play from 1:06:00

1:09:00 After two seconds, it goes from Hello Global to Hello world

Yeah, 100%, I don't know that we have, um. Yeah, any, any samples for socket IO directly, but for the CON, the notion of websockets and real-time communication. We definitely have, you know, proof of that out in the wild. I want to address this one real quick. It's it's actually pretty interesting, uh. I'm going to use XState for some complex workflows in my apps. Check out, for example. It will definitely replace some of my React contexts. Now, you could still use context with, you know, XState. But I wanted to show you, like, just an example of, um. In fact, I'm going to make just a small, dummy example over here, H1 and just call this something. I'm improving by the way, but okay, so we see something over here. Let's say that you wanted to basically have this Global store, and you could use XY. Both at the global level and the local level. But let's see, once machine equals, create machine, and let's say that we have context.

I don't know. Message, hello, Global world, whatever. So probably the simplest machine that you could think of, and like we learned about at the beginning of the webinar, you could have on. You could change this however you want. Which actually, let's have a little fun with this. Uh. So initial Global, because I want to show off another feature too, there are so many features actually, so states Global. And then, let's do a world. And in this world, we're going to assign a message to Hello world. Okay, so I'm just going to say, after two seconds, that's a feature I want to show. Delays. Yes, yeah, yeah, just go to world. I'm I'm too lazy to type the object over here. So we have this machine, but we need to actually make that a live store, so con actor equals, create actor machine, and we could also start here.

It's fine. And so now let's say that we want to read that in here. Well, and this goes into it nicely, transitions, no pun intended, transitions to the topic of having framework, Integrations. So we have this, message equals you selector, really, really useful hook, where you pass in the actor and then you read the state, so this would be state. context. message. And now we. Could just pass that message here, beautiful, there we go. After two seconds, it goes from Hello Global to Hello world. You know, and of course, we could go back and we could have it be infinite, so we could just paste that here. There we go. So now, every two seconds, it's just going to go back and forth between Hello Global and Hello world. So this is like a store in the traditional sense of like Redux or Zustand or things like that.

But you could also model effects as well, and you have built-in modeling of delays, so I feel like that's pretty nice. And also if you wanted to send an event, you already have the actor instance over here. So you could just say, for example, Onclick equals, actor. send type. Good goodbye, and so this is fun, so we could just say on goodbye. Actions assigned, we're going to say the messages, goodbye, sweet world. Oh goodness, that sounds morbid, I'm sorry, but okay. D yeah. So it goes back and for, and then when we click it, say good, but it's only temporary, so that's, that's a good thing. It's only temporary because we transition. And then, yeah, yeah, wow, this is, an unintentionally existential machine. But I love it, I'm here for it. Yeah, but yeah, so I just want to show like this is the way that you could do a global, you know, a basically a global store.

In X8. We also have, you know, create actor context, which is a helper for creating React context. That, and it, it has providers and things like that. If you did, want to use React context, which is useful for a lot of things. Yeah, yeah. I also want to shout out, well, really quickly. Before this one, I wanted to shout out back to Sasa's question about multiplayer and things like that. That if you had something like a session and you needed a global con controller for the session, this is a good approach to dealing with that. And you can still have that actor speak to all your individual members, which is cool. You feel like a puppet master once it all gets working. But yeah, moving on, from Scott Resnik, Hey, I. Know that guy, literally just learned from watching. The logic. Expressions not and a TypeScript have parameter type inferencing from the return type, so looking forward to seeing the additional inference featur in the future. I'll tell you, Scott, I had everything to do with it and you're welcome.

No, not at all, but yeah, glad to see that, that you walked away with something. Yeah, go, oh yeah, sorry, yeah. Andre saying, yes. I'm also looking into using XState for app state stuff like session login, logging out, E.t.c. Yeah, it's great for that. It's a good way to make sure that nothing ends up in the wrong place and that everything gets cleaned up. When you're transitioning from one thing to the other, which? If you find yourself dealing with anything temporal, anything like that, you know you need to worry about timing with. I found that just using a state machine in general is just helpful.

Play from 1:09:00

1:15:00 When you start an actor system…

Yeah, and by the way, I want to say that if you wanted to get started, like maybe you don't want to jump into code right away, you could always just model it visually using Stely Studio. And, we have a nice, you know, get started section that teaches you how to use the different parts of the studio. Add states and things like that, and also greeted with a nice little info panel that shows you. Exactly what you could do, like double click to add a states, drag to add a transition. Things like that, and you could simulate and, you know, do everything, uh. But we also have these two new things here. Opening code sandbox and open in Stack Blitz, so if you click one, and sorry, I guess today is Stack Blitz day, then, you will get an error. Oh no, of course, this happens when we stream.

No, that's, yeah, you know what, there we go, yay, non-determinism to the rescue. I literally did nothing and it just fixed itself. But anyway, we basically have our state machine and we have a nice little UI over here. That lets you click through the possible events. This, by the way, there's no Frameworks over here and no dependencies besides X, states and VS. Of course, because that's how it runs, and. Yeah, so, you know, let's say that we click feedback. good takes us to thanks, close, restart, so we basically have that same form feedback. bad. And then we could submit, and then, you know, have done invoke submitting, and then we go to closed. In the future, we're going to automatically generate forms for you to actually add events, payloads and things like that. But for now, this is just a good way to say, to basically see how you could use your state machines in actual apps. Yeah, plus one we got, we got one question I do want to call out, from Patrick.

Saying I remember seeing something about a completely revamped or new actor system functionality in V5, correct? Are there any docs out for this system yet? Outside of PR descriptions? Great question, Patrick. The answer is yes, the docs are available. It's you can get there through. Oh, it is stat. AOcs, and just select the AATE V5. Yeah, drop down there, so um. Full disclosure XState 5 is in beta, and conversely, so are the docs. So we're still working on them, we're still fleshing things out. But we do have, I think, a lot of, really deep documentation to get you started. Yeah, exactly, yeah. So a system, you know, what Patrick is referring to is, basically, a collection of actors, actors that all might know about each other. You know, basically when? When you start an actor system, you start with a rude actor. And that rude actor might spawn or invoke other actors, which themselves might spawn or invoke other actors, too.

And so sometimes it gets difficult to get one actor to communicate with another actor. If they don't have a direct child parents relationship, you know, they might be siblings or otherwise. But you might want some actor where you could reference it from any other actor, the solution to doing so is by registering an actor, when you, for example, invoke Sponded. So you would give it a system ID. In this case, I give it a Notifier and that way any other actor in the system can just call system DoGet Notifier and send messages to it. It doesn't matter where that actor lives. So it becomes this sort of I. Don't want to call it Global, but it's a systemwide lookup for actors, and so that's one of the benefits of a, an actor system. But it's not something new that you have to learn. Unless you want to use this functionality, everything works basically the same as V4 conceptually. So, yeah, I also want to shout out there that, um.

As part of the studio, we made sure to model this actor system in such a way that you don't have to Bubble up. If you have, like, several children, you don't have to Bubble up each child's parent to get to the system that they belong to, every actor knows what system they're in. I'm very excited about that. It took some, took some soul searching to get that relationship, but we got it. I'm very happy about it, right? Yeah. We also have an extensive guide for if you're coming from X8, V4, we have a comparison on things that are deprecated between V4. And how you would write them in XState version five. So you could just go back and forth and see how they change. Honestly, it's not that big of a change. And we do plan on providing code mods to automatically do this. And if you don't want to use code mods, just ask me.

Because I've migrated probably hundreds of machines myself. It's, it's second nature now, like, it's, it's really not that difficult to do. But the syntax is very, very similar. So I imagine you're not going to have a hard time, you know, migrating between X8, version 4 and version five. Yeah, as a matter of fact, in the studio itself. We have the option to export your machine, as either a V4 machine or a V5 machine, and you can see the syntax change live. Yeah, so yeah, so without making this like a 4-Hour workshop or anything, uh. We covered the basics of what a state machine are, and we touched on some things, that are, related to. Statecharts such as nested states, final states, or, sorry, they're called child states. You know, parent child states, final states. You know, done. Transitions, invocations, actions and things like that. There's so much more to learn with XState, but I do.

Want to emphasize you don't have to learn absolutely everything about XState in order to start getting productive, sorry, productive with it.

Play from 1:15:00

1:21:00 Great, so we add oil and so we're soaking the potatoes

There's a lot to learn. So you could look at our documentation. You could also open this question mark in the sidebar. And actually, right now, you could even use AI to generate your flows. This is a pro feature, but if you are a free user, we give you three, free Generations per month. That that's new as of today. So, you know, you could say, what kind of machine should I make? What's a good Friday machine? How to make French fries? I have no idea how to make French fries, so I'm just gonna put that in here. You, you could get as creative as you want, but if you do want inspiration, or you want to see, like, Okay, how is a state machine actually made? Then you could just click generate flow and hopefully, if everything works, it's going to, generate a state machine for you. And that gives you a really good starting points to work from.

Where you know, you could basically take that and, use it in your application. So there's a lot of steps, but this is actually really cool, so I'm going to click simulate and let me show the active state. Add potatoes, so then we're preparing the potatoes for frying, and this is great. There's even an assign action, so it's assign assigning. Oil. I love it, I really, really love it. Okay, great, so we add oil and so we're soaking the potatoes. This is really it's a statechart for. UM. And you could add salt, you could remove salt. I have no idea how you remove salt. I guess you just wash it or something I don't want to know. And then you, you uh. Dry it, so you're drying the potatoes. Add more oil, apparently. MH and then you fry them, so they're cooking. And then eventually they're ready, if they are ready. So we have a nice guard over here.

So this is something that you could generate using AI, and, yeah, just use PRS. Yeah, I always want to say that, you know, the intention behind the generate. Flow is to sort of erase that feeling of, stress you get when you're looking at an empty, blank canvas, right? Like, no one wants to write a paper when there's nothing on the page. So this is a really good way to get started. But, you know, we don't rely on the generate flow as a wholesale, you know, this will work 100% perfectly. Every time that's, you get the Gavin disclosure there to say it. And if you prefer, you know, human, human-made machines, then, of course, there's a lot of over 20,000 examples for you to choose from. Like, let's go to this David guys, machine over here. Yeah. This is just an espresso machine that I was working on, and, spoiler alert, I did use AI to help me out here. I just wanted to model a nice espresso machine.

Yeah, lovely. We got one question.

Play from 1:21:00

1:24:00 Back to your GitHub repo right now…

I know we're we're over time, but I do want to take this one, Patricio says. For devs not using VS code, what could be a good workflow to still benefit from Studio features without doing too much of a manual effort and switching context too often? I think this is an excellent question. I have my own preferred workflow and it's very opinionated. And so, David, I'm going to give mine, and I want you to give yours. So, what I tend to do is keep my editor open. My I do use VS code, but I don't necessarily always use the, the XState visual extension. So I'll keep my editor open on the left, and I'll keep the studio open on the right, and I will draft my machines and my flow on the right. Do a quick simulation and if I like it, export it and then just copy pasta that over to my editor on the left.

And that gets me, pretty much all the way there. In terms of having a single context, we were talking about this morning as a matter of fact. The instant I hit command tab there, it's anyone's game, whether I'm coming back to that tab or not, you know, it's it's switching. Context is a productivity killer. So what we're also doing to address this is making sure, that we're, we're testing now, but we're. Building in GitHub integration as well, and that'll allow you to make sure that. Hey, whenever I do a commit in my local editor, it's going to stay in lock step with what is in the studio. And that I think will, and vice versa. Obviously, changing in the studio will count as commits, if you want them to, will count as commits. Back to your GitHub repo right now, we can import from GitHub.

But we're, soon to be releasing a full-on back and for bi directional SYNC feature. And I'm off my soap box. I'm sorry, I just wanted to take that question. It was a good one. Thank you, Patricia. Yeah, yeah. So, like Evan said, I think the best way is going to be eventually, using a GitHub, you know, just GitHub syncing. However, we do want this to be available to people who use other editors, or maybe they use VIM, or, you know, EMAC or Nano. I'm a nano person because I don't have the hearts to my goodness. Learn, I know, I know, but yeah, what you could do is actually, yeah, we. We do have an experimental, you know, GitHub SNLe ready. So try to remember where was it in here? Yeah, sure, let's just search all. So we are, yeah. In syncing with the repo, we scan the repo that you give us access to and find all the files that could be Exate compatible.

And we'll let you know if they do or don't have machines associated with those files because XState F, XState machines can be in JSON TypeScript, JavaScript. What have you? So we do that scan and then we pull in what we can find and yeah, like, David showing off. There's, there's his donut machine that is taking up some someone's server space on GitHub for some reason. Actually, one of our, someone else on our team, Jenny made this toing the machine, and so, oh, it's Jenny's machine, then it's excellent.

Play from 1:24:00

1:27:00 Hopefully my camera works now, that's a wrong camera…

[Laughter] SAS asked, I need someone to consult me on a game I'm building, willing to compensate anyone interested. Yeah, so, two things first of all, like, on Discord, we have a, you know, big Vibrant community of people who. Are I'm? I'm pretty much always on Discord, so I'm always willing to help out when I have time, as well as other people on our team. And my camera just shut off, it went in that state, but that's okay. Yeah, and now my mouse isn't working, but that's okay because you could still see my screen. But anyway, yeah. So there are, you know, people willing to help on Discord. It's basically like free support. I did want to mention that if you go to St. Le.. Pricing, don't worry about this. By the way, this is ridiculously cheap, cheap. Anyway, uh. In our services, we like, we do encourage you. This is brand new, by the way. We do encourage you to contact us if you do need Consulting, workshops, custom solutions, or priority supports.

Because we're a small team. That's, you know, working really hard to make all of these tools. And, we're even making tools, that will help you even if you're not using XAT. So we're, creating documentation, diagramming, test generation, visualization tools, which I guess goes hand in hand with diagramming. So, yeah, anything you could do to support us is really, really appreciated. So, yeah, just talk to us in case you have any special needs like that. Yeah, plus one, oh yeah, and Michael really quick said. We use XState inspect and XState type 10. One of our biggest priorities before we release X8 version 5 is we do want to get those compatible with, well, with XED version five. So that is one of the very next things that we're working on. And, hopefully my camera works now, that's a wrong camera, but that's okay. Uh. So, hopefully we will have those out, of course, by the end of the year.

Yeah, sooner rather than later. And yeah, so. So that would be one way where you could really take advantage of the studio without having to have the VS code extension. So yeah, yeah, if you're doing V4 machines, the CLI is really good. I'd forgotten to mention that, so thank you for shouting that out. Michael, but yeah, in order to make sure that I'm I'm as up to date as I can be, I just have the studio off to my right. And the my VSS code editor off to the left all right well it's been an hour and a half of really fun webinar and teaching you all the intro to XState there are so many features and again you don't have to learn them all it's actually pretty quick to get started if you for some reason zoomed to the end of this webinar then just check out the first five or 10 minutes and you'll be up to speed pretty quickly everything else is just you know really useful extra things that you could do with state machines statecharts the actor model and XState I really enjoyed this I really enjoyed talking to all of you same here yeah I had a great had a great time thank you SOS for the email just email support stat. thank you somebody will get back to you in a heartbeat yeah and if anyone else you know just looking to chat with the community ask some questions you know provide feedback feature requests reach out to the team the best place to do that is to hit us up in Discord I dropped a link to an invite link to our server right in the chat so yeah feel free hop on in all right thank you everyone bye for now

Play from 1:27:00

Related talks