XState Fundamentals (JavaScript Marathon)
Watch on YouTube (This Dot Media)
What is this talk about?
“If anyone has any questions on what we've done so far to just like, think about the events and how we would model, this sample media player application.”
“When the play event happens again by the user, we transition from pause to playing.”
From the opening of the talk.
Key takeaways
- If anyone has any questions on what we've done so far to just like, think about the events and how we would model, this sample media player application. 10:00
- When the play event happens again by the user, we transition from pause to playing. 19:00
- Where we're not really going to be doing the skip song thing, we're going to be focusing on, play and pause. 24:00
- All these are just sending the exact same events, so if I press play now, we're in the playing state. 30:00
- You start to notice a pattern, you see that every single transition that comes into the playing states starts the player. 48:00
- Actually, instead of using Star player and stop player, we're going to be more methodical about this. 1:03:00
Quoted from the transcript.
Full transcript
From YouTube auto-captions. Punctuation and capitals were restored automatically. Technical terms were normalized; some errors remain. 13,009 words.
0:00 Introduction
Hello and welcome to JavaScript Marathon, a full week of free online courses in some of the leading web development technologies and concepts. Today's trainer is David Khourshid, founder of Stately and creator of XState, presenting XState fundamentals. If you have any questions after today, feel free to follow David at @DavidKPiano on Twitter. A special thanks to this week's sponsor, This.Labs, offering personalized training programs to suit your organizational needs, ensuring you and your company stay on the leading edge. If you find keeping up with constantly evolving technology is a struggle and want to bring your team up to speed on one of the latest technologies. Contact us today at Hi this dot Co. to set up your complimentary needs assessment. This.Labs is hiring. We are hiring engineer managers and senior software engineers. If you are interested, send us your info at jobs this dot Co. We're winding down the year, we do have a couple more events for the rest of 2021.
State of React happens on December 2nd, GraphQL Contributor days on December 7th, state of Angular ecosystem on December 9th, and our monthly mentoring happens on December 15th. We also have two more stops on our Angular and React world tours. The Angular world tour stops in Tokyo on December 1st and the React world tour stops in Mountain View, California, on December 1st as well. And finally, JavaScript Marathon is wrapping up for the year this week. But we are going to be back in 2022, March 14th to 18th and stay tuned to see what those sessions look like. And with that, I will turn it over to David. Hi everybody and welcome to JavaScript Marathon. Today. We have a very special guest, David, who is going to be, teaching us all the awesome, amazing things. For those of you who don't know, David, oh, my gosh, David. I remember when you first started X day, then the whole, the whole world started screaming about state machines and it being so awesome.
And I think education on this is so important. And you have a lot of other stuff going on. So if you want to do a quick intro and then we can just get straight into the training, sure. So, yeah, my name is David, I've been a developer for about 10 years. I. I was at Microsoft actually for the last four years, but I've been working on this open source project called XState for the last six years. And eventually, there was a point where I realized that I needed to work on this and related tooling full-time. Because, just the idea of software modeling is so important in our everyday developments. But there aren't really that many good tools for that. And so this is something that I really want to solve with the tools that we're creating. Over at Stately, so, I'm the founder of Stately.
3:00 If you don't like the song…
And there's a whole bunch of awesome, developers working for us, and we're making some really, really cool things. One of the things we just released is actually this visualizer, which allows you to create state machines. And we're going to talk a little bit about that. I'm sort of jumping ahead right now. But like you could say initial loading states and then give states, and I know that this is tiny. I just want to show you in general what this is. Loading success, so you could, like, define your states and then you could say on [Music] loaded success. And so this visualizer allows you to create these state machines really easily. But again, this is me fast forwarding, so I really want to instead start at a blank slate. And if at any time anyone has questions in the live chat over here, please just raise your hand, because I really want this to become an open discussion.
And so, typically, when we talk about like state and software modeling and state machines, and especially XState, uh. The library I created, which is a library for state machines and statecharts. One of the biggest questions becomes, why would you even reach out for a library like this? There's umpteen different state management libraries, and you know it, it could be hard to choose one and hard to see. Like, what's the differences between? Like, you know what each state management library does and how it's going to, you know, help me accomplish my goals in my app. And so where do I even start if I want to get started with state machines? And so before we get into that, I want to just talk about just being. Able to model your application logic visually from very first principles. Even if you have no idea what a state machine is, that's where we're going to start a completely blank slate.
So, and I'm going to be using ExcaliDraw for now to do this, but eventually we'll have a visual editor that makes it a lot easier to create state machines. So imagine that I have a really simple media player app that I need to build, and it has a few features. It has the current elapsed time, it has a, you know, thumbs up, thumbs down. If you don't like the song, you could press play or press play, press pause. Try saying that five times fast, or you could click skip in order to skip to the next song. So it's a very basic media player. And if you happen to have a Tesla model 3 or any of the Teslas, then you'll recognize this immediately, except without all the colors. But that's sort of what I modeled that off of again. It's a really simple interface, and, this is probably something that is about the level of complexity that you might encounter in normal apps.
So when we think about state modeling, we're really thinking about how do we model complex application logic that might start off simple, but might get complex later? And how do we build, to? Just to make those kinds of future changes a lot easier? So the question becomes, you know, where do we even start? So, the first thing that I would say that you would start from is, think about everything that can happen in the app. So I'm just going to label this as, oh, I need to zoom in a bit. There we go, we're gonna label this as events. You know, we have a bunch of events, and these events are things that can happen. If you're coming from Redux or NGRX or UX, these might be called actions, but the formal term, I guess, a mathematically correct term. I mean, there's many different terms for these signals, messages, events, but we're going to be calling them events, because these are describing things that happened.
So what can we do in the media player app? Well, the user can play. So, you know, just. Press the play button. The user can also pause and let me zoom in. Oops, zoom in a bit here. So it's good to think about, like, what else can they do? Wow, 500. Ooh, this goes slow. Okay, whatever, that's fine. So they could also skip ahead to the next song, they could also fave, which is, you know, giving it a thumbs up, they could unfavor it. And so these are just the things that a user can do. Let's see if we got everything save on, save, play, pause and skip ahead. And so now we have a good idea of, you know, what things can change the states of our small application. But these aren't the only things that you should consider in terms of events, too, because these are just what comes in externally from the user. However, there could be other events too that you need to think about.
And so the best way to think about it is just envision how this media player works and what changes. So, even though we could press play, press pause, we have this timer over here which shows the elapsed time of the song. And so, when the when the music's playing, it's going to go down. So that state is changing. It goes down from like 123 to 122 to 121. And so, one important concept that you have to keep in mind with state machines and pretty much all of programming, is that when the states change happens. There is always a reason for it, and these reasons can be described via events. And so, I would just say, like, I'm just going to call this a tick, so a tick, like a ticking clock a. This would represent the internal audio player saying, Hey, this much time elapsed, and so it would, you know, a tick would just say. Or actually, we would, you know, call this like, a lap. So, in events coming from the audio player saying, Okay, now there's one minute left, you know, now there's half a minute left, etc.
And so those are those are external events. And I'm going to color this differently just to show that, you know, this is external, this is that's too close of a color. So is that all right? We'll. Do that, this is internal now, these events, you, you pretty much treat them the same, when it comes to stay machines. So we have all of our events, and you know, some of you might try to skip ahead and think, okay, well, now we have the events. What are the states? And so I would actually say, don't think about the states yet. Finite states are more of an emergence property than something that you have to think about upfront. So this would definitely be a good place to start. So, in thinking about how all of this works, you know, we have all these events happening, and those events are going to change the state. So typically what you might do is you might have some sort of is playing variable, you know, is liked, is unliked.
And just all of these boolean values. And so what we want to do is translate those boolean values to, to just finite states. And so, yeah, this is where, you know, we sort of get into XState. So, yeah, just to introduce the API to you. And actually, I'm going to stop there and pause for any questions. If anyone has any questions on what we've done so far to just like, think about the events and how we would model, this sample media player application. So, just a little question about this. And I noticed that I have been doing this for other frameworks, like you say, reducing your ex. So, basically, what you're trying to accomplish is to have a an overall idea of all the events that, happens, or they're, yeah, can occur at some given point. The application, and the different actors that can, interact with it and use that as the guiding force of your architecture.
Yeah, exactly, and so it all starts from the events. So, yeah, I'm just gonna put states here. So, yeah, your, your intuition is exactly correct. There you're, you're basically collecting all of the LeGo pieces that sort of, you're gonna bring together and use to construct, the rest of your application. Logic. Yeah, so when we think about states and I'm gonna, you know, just make this white, like I said, we. Have some, zoom out a little bit. We we usually use booleans, at least when we're first starting out, and so that's fine, so start off with that. If you're used to that. And you might, you know, have something like, is playing, true, right? And then, you know, eventually that boolean might become is playing false. And so if you're starting off with the media player, you might, you know, use this. But you have to ask yourself two things first of all, what can cause this boolean value to change?
And so the answer is, that's the wrong line, but yeah, there we go. The answer is that, if you press pause, so I'm just going to put a pause event here. Oops, pause. Then it goes from is playing to false. However, if we play, then that is playing becomes true. So I'm just going to put this up like that. And so that's how these can change between each other. And typically, when you have a boolean value, or any sort of value that represents a mode or a state, well, then that can be considered a finite state. Also, there's a difference between finite states and infinite states, so, infinite state would just be data like how many seconds have elapsed, whether it's liked or unlikes. Like those aren't really different states, even though it is a bullying, it's just something that's qualitative, or, sorry, quantitative, not qualitative, and so, yeah, with finite states.
14:00 When the play event happens again by the user…
You actually wants to think about the behavior, and so what is a behavior? A behavior is something that says. When I'm in this mode or this behavior, only these things can happen. And so if I'm in a different behavior, different things can happen. So, for example, is playing true, like, let's say that we're currently playing? If the user were to press play again, like, let's say that there was another button for play, then it's like we're already playing. So nothing should happen. We're not going to tell the audio to start the song because, or the media player to start the song because the song's already playing. Same thing if it's paused, if the user keeps pressing pause, like if it were a separate button, like in older car interfaces, then, nothing should happen. It should ignore those events. And so that's a difference in behavior. The analogy I like to make is it's sort of like, as a human, you know, you're either asleep or awake.
You can't be both asleep and awake at the same time. And you behave differently when you're asleep rather than when you're awake. When you're awake, you're attentive, you know, if things are happening like something's on TV, you might be responding to that, but if you're asleep, you're going to respond differently or not at all to, to many events. So, these booleans are going to be a good way of, like, indicating that, something should be a, a finite state, rather than, you know, just data. Well, that shrink for no reason. All right, there we go. And so now we could just convert these instead of being booleans, we, these are really good candidates for converting, to finite states. And so let's do that. And so step one is to consider what is your initial state. So when you first get in the you know, in here, I'm going to assume that it's paused, because it's like, we don't know if you want to play yet.
So I'm just going to say, you know, paused is our initial state, and then we're going to copy this over and say playing. So now, depending on what happens, you know, of course, we have a pause event and we have a play event. And you know, there's other things that can happen too, but we're just going to be focusing on those two for now. So a play event. When you're in the playing states, remember, this is a behavior, it's going to take you to the past state, which is a different behavior. And so same thing if you're in the apostate and you go to the playing states, you know? Or if you're in the apostate in the oops, that's the wrong way. Okay, we'll just switch it like that, all right. So if you're playing pause event happens now, you're in the past stage, if you're in the past eight play event happens now, you're in the playing state. And additionally, we would have a an initial state.
So I'm just going to copy these over here and this. Is how an initial state is, you know, is denoted. So we have a little dot with an arrow that says, Hey. This is where the machine should end up at first, and so this becomes a very basic, a basic state machine. And so you might be thinking like, Okay, we moved from using booleans to now using, you know, using just two separate states, and you might be thinking, Okay, well, that's a little bit annoying, like, why? Why can't we just use booleans? Like there's two states? Well, especially with, like, a car audio interface. The problem with using only two states is there might not just be two states. For example, if a song is loading, we need some way of representing that, and so we're not going to do it in this application. But just for example, sake. We're going to say, you know, there might be a loading state.
And so if we're playing, or if we're in the past states, then something might happen that might cause us to go to this loading state. Right? So, you know, whether we're in pause or playing? Yeah, I'm just gonna copy this there, so we'll just call this buffering or something. Well, whatever the audio player tells us is happening. And so when we're in this loading state, at least in the car interface, this turns into a spinner. So you can't play or pause. And so, you know, now we could just go back from loading to playing or to pause, depending on. You know where you were, uh? So that's why, like, introducing new states becomes a lot easier. When you, when you use it, or when you use finite states, rather than when you use booleans. Because, remember, booleans can only represent two values. And, with finite states, you could represent a lot more values.
Of course, a finite number of values that way. So I'm just going to get rid of this loading state for simplicity, and yeah, so just some technical terminology just to review. We have the initial state which is paused, we have another state which is playing. And when the play event happens again by the user, we transition from pause to playing. And so when we're in the playing state, and. The pause event happens, we transition from playing to pause, and this is called a transition. So this arrow. We have an event here, and the events is, you know, the event of the transition, and the transition says we're going between these two states when that happens. Also, it like, it doesn't really. It's not really necessary to change states when you are actually this should be over here. Sorry, trying to draw and talk at the same time, but it's not necessary to, change states. When you have an event, so, for example, we could have an event that go back here and bring this to back.
Okay, so we could have an event. Like, fave and I'm just going to put this in here, and so this fave event can. It basically doesn't need to change state. So it's just like, you know, in an invisible transition, that only does an action. And so, that's something that we're going to talk about, too. So faith shouldn't really change any of these states, but it should do something, and same thing with, with unfave, that should do something as well.
21:00 All the installation instructions are available if you go to xc..js..org…
But before we go too far into this, we're, and, you know, gonna go back to XState. I wanted to pause for any questions. Here so far, like just in modeling this, I mean, so far it's a basic state machine, but it's going to get more complex. All right, no questions. You must just be like, the best teacher ever, I guess. Or, yeah, maybe this is really basic stuff, which, you know, if all of you did your homework ahead of time and learned this, then great. All right. So, let's actually get into X data and see what it's all about. This is a React app, and, we're actually not going to be touching the React part of it yet. I just want to focus on the machine part. And, if you want me to zoom in, I could probably zoom in a little bit more, just so that everyone can see. And yeah, we still have everything visible here. I wish that I could hide this. Can I? Nope, Oh yeah, I can. There we go, Okay, cool.
So, the way we create a. Machine with XState and, of course, you could npm install XState. All the installation instructions are available if you go to xc..js..org, docs or the GitHub page. Then, there's a bunch of templates for you to get started quickly. Depending on which framework you're using, or if you're not using a framework, that's completely fine, too, you could use XState without a framework. And Google's talking to me because it's a faulty state machine. So, yeah. There's also instructions, installation instructions in the GitHub, just npm install XState pretty straightforward. Yeah, so let's actually create this machine that we were talking about. So you would use create machine, and then you would add an object now in this object. By the way, by far, the simplest way to start with a state machine is to have a single state. And, this state, is actually implicit. So it's like the default route state of the machine.
And it looks exactly as you're seeing right now. There's nothing in this object, it's completely empty. But we could add on and then we could start to add events that might happen. So, we could say, and just for convention's sake, and you don't have to do this. But I'm going to uppercase all the events just so that you could easily see the difference between them. So, you know, we could have fave, we could have unfave, we could have play, pause and skip. And so these are going to be all of our events in the machine. And these could all do stuff. So the place that we hold, like the extra state, the states that's not our finite state, is in context.
24:00 If I send it the pause event, it's going to go…
So you could think of it as like contextual data for like, specific to the state machine. And so, you know, we might have a duration. Let's say that it's, I don't know, 300 seconds long, which is what five minutes and elapsed. So far nothing elapsed, and so that's going to be for the time over there. And of course, we have a boolean for, babed, and this is going to be false. And yeah. So, where we're not really going to be doing the skip song thing, we're going to be focusing on, play and pause. And, you know, just for, you know, starting off, we're going to actually add that, that smelly boolean is playing, and we're going to make it false. So this, if you've used Redux or VUX or NGRX, this is going to feel just like a reducer. Except it gives you this nice little structure of, you have your data over here, you have your events over here.
So you don't have to write any of those, annoying switch statements and everything that happens in here. So, just to try it out. [Music] Oh yeah. So this is a transition object, and so in the transition object. You could have a target which is like which state it goes to, but we're not going to any state for this one. And you could have actions that say which actions are to be performed when that transition occurs. So we're also going to pull a sign from XState, which is an action creator that, you know, allows you to modify this context. And so we're just going to say, fade true. And this is React specific, but if you're not using Reacts, then it's also very similar. In Vue. And I think in, with any of the adapters, uh. The only important thing is, you know, the machine, the machine is completely framework agnostic, so you don't have to, really worry about that.
So we're going to hook up our machine to that, that fave, so I'm just going to find this one. Okay, so this thumbs up, uh? The used machine hook actually comes from X8 React, so you could just pull it from there. And it's going to provide you two things. Very similar to useReducer, it's going to provide you the state of the machine, the overall state. And send and so send is like dispatch, if you're used to useReducer or Redux, same thing. So we're just going to send an event object with type of faith. And so, this is going to console log the states, I want to log the context, just to show you what's going on inside. Okay, so we have all of our expected data. 300 elapsed. Faves false is playing false when we click, plus now it says fade true, so we know. That that's working, and you could just, you know, copy and paste this here.
We want to assign fade to false [Music], and so this also highlights that everything is done via events. Oh, of course, we didn't hook that up, so let's hook it up. This is going to be unfaith. So, essentially, you could treat XState just like you treated every other state machine, or, sorry, state management library before in the past. You have your actions and so you could just assign and that's going to change context. And so already it works exactly the same way as Redux and related libraries. But one of the reasons that you would use XState is to actually like orchestrate the different behaviors of your application. And so that's where this is playing comes in. Of course, we could do, is playing true? is playing false over here, you know? So if I just, oops, I just added these here, action so is playing, this is going to be true, and we would say, is playing false.
You know that might work? So obviously we have to add that too. Let me do that real quick. So, play, and also, this is gonna be skip, so we have play, skip, and so I forgot the pause button, so let me add that real quick. This is like one of those cooking shows where it's like, by the way, I have a prepared cake in the oven, except no cake exists. Everything here is being done just from scratch. So, I'm just going to have a pause button over there. Cool, so it says is playing true. You can see that over there. If I press pause, it's playing true. Because I forgot to do this. So true, false. Nothing really that impressive right now, however, from what we modeled in our, scale jar over here. These playing and pause states are really different behaviors. And we're going to want to separate that, so that we could better orchestrate.
Like I said, what happens when our app is in each one of those behaviors? So let's go ahead and do that. Where we first have to define an initial state, and so our initial state is going to be like we said. Paused and then we have an object that represents all of the states by key, so we have a paused state and we have a playing state. And now we want to go between those states. So we're going to get rid of this boolean because we're replacing it with these finite states. And, yeah, so I'm just going to get rid of that. And so when I'm in the positive state and the play event happens now, I want to go to the playing state. So instead of logging the state.context, we're now going to log the state.value just to see how that changes. And remember, I didn't change the UI at all.
All these are just sending the exact same events, so if I press play now, we're in the playing state. We didn't hook up the pause event yet, so, let's go ahead and do that now. If we were doing a workshop, I'd tell you all to do it, but, that's okay, so pause. But by the way, just Fyi. I think there were some a few questions whenever you're ready for them. Yeah, yeah, absolutely. So, let me just make sure, all right. So we're in playing. Oh yeah, sorry, I have to on pause, target paused. Okay, cool, so pause, playing, pause, playing, pause, you know, not too interesting yet. We're going to see when we actually start to add, you know, add interactivity, how this is important, but I'm going to pause there for questions. I think one of the questions was, well, can we use XState outside the React component?
Yes, absolutely, you could use XState, pretty much anywhere. And actually, let me demonstrate that for you. Real quick. I, I sort of jumped ahead and went straight into, reacts. But yeah. I want to show you how this could basically be used outside, and there's really two ways. First, you could use that machine that we created and we called it media machine, just for reference. You could use that as a pure function. And so this is how, if I say, so const next state equals, mediamachine dot transition, this is going to be a pure function. And it takes two expected arguments, which is the state. And of course, you'd have to recreate. That whole big state object, but I'm just going to put undefined and this means the initial state and then the event. So we're going to say type play, so if I console.log nextdate.value, then oops value, then you're going to see that it's playing.
And so now I guess I'll call this, next state, we're going to take that next state. I'm going to send it, well, actually, let's see what happens when I send it. The same events. Obviously, nothing is going to change. You know, it's going to go playing, playing. But now if I send it the pause event, it's going to go, oh, next state value, it's going to go from playing to paused. And so instead of using value, if you see the entire state object, then you get a lot of things in here. So let me just point out the important things. The first one is the value, and so this is the finite state value. So this would be right now either playing or paused. The context, which is all of that data, that extra data that we have. And other things that might be useful are, events, so you have the actual events object that you sense to the machine, right in that state object, too, in case you want to do anything else with that.
And there's a few other useful properties that we're going to take a look at soon. But, for the most part, only these two are the ones that you really need to care about in most applications the value and the context. But yeah. So the second way, to interact with this outside of React or any framework is by interpreting it and making it like a live object that you could send events to.
34:00 I think it's like something like state equals media service
So we're going to call this media service equals interpret, and we're going to import that from XState, you give it the machine, so the media machine. And also on transition, I want to listen for the states. So I'm going to console.log state.value. And you have to start it because it doesn't start immediately and it waits for your permission to do so. So now if I, if I see this, you're going to see that it's going to log pause because it starts the machine and. Says, Okay, here's the initial state. If I send the media service in event, so send type pause or, well, it's right, so play, then, it's going to log that it's playing.
So, yeah, those are the two ways that you could use it outside of React. And hopefully that answered that question. And then, another question was, how do we derive state? [Music], so what is meant by deriving state? If you want to clarify? Yeah, I was thinking something similar to what selector stores in NGRX, where you have the whole state. But maybe you don't want to pass it completely to a component, or you don't want, or you want, something built upon that passed to a component. So how could be the recommended way of transforming that state to use it in other place of the application without having to, transform that every time? Oh okay, so are binding tunes, are using React, or just in general? Are you talking about? just in general, but React wars? Okay, okay, yeah, so React specifically. There's, there's two way or not two ways, but there's, two hooks that you would use for this. So remember that service I created, I'm gonna, copy this out.
If you want just the service, so service equals. Use interpret media machine this use interpret hook is only going to return the service and so that service can be subscribed to. And it's only ever going to render once, so it's not going to cause any re-renders when the state changes, no matter how often it changes. And so the way that you could select a value, let's say that we want to, have a is playing like going back to those, those booleans, but this time it's derived, so it's okay. We would use a U selector hook, and so this U selector takes that service. [Music]. And then we would just say, state dot, you know, you could say state dot. Value equals playing, or you could also do state.matches playing. And that's sort of a built-in method over there. So I'm going to console.log is playing and show you. Like, this is just a small example of a, you know, of a derived value.
Oh, and. It says send is not defined. Thankfully, we could just, grab that from service, so I could say consent equal service dot send. So, yeah, you see, is playing true, is playing false, and now this is only going to re-render if, you know, it is playing, changes. So whatever we calculate in here. So if you've used Redux before, it's very similar. The only difference is you have to pass that, you know, that service into there. And so that's in the uh. React stocks. So otherwise, if you wanted to, just, you know, figure out how to select values outside of it. This, for example, in Angular or something else. This service is subscribable, so you could say media service dot subscribe, so it is subscribable, it adheres to that. So if you want to map values in RxJS or whatever, you get the state over here and you could transform those.
So I imagine with RxJS, you would pipe it through. And then, you know, distinct until changed or something like that. And yeah, so any? Any selector solution that works with, you know, something that's subscribable, is going to work the exact same way. In short, you get the state here and then you can respond to that state and say, only do this if this part of the states, changed. So, yeah. The U selector hook is available in React and the View libraries. And yeah, so hopefully that answers your question. As far as making it, making general selectors, it's still something that we're thinking about, like having computed or derived values directly in the machine. That, still we. We want to make sure that we design that right. So likely that might be a version five thing, but it will definitely be a cool addition. So awesome, thank you. One of my other favorite questions is, how good is RxJS integration?
Oh yeah, so, people have been. What's funny is we built adapters for, reacts, we built adapters for Vue, like just the hooks and you know, the composition, API stuff, uh. But for Angular, we sort of didn't touch it, we didn't make any adapters for it, uh. But part of the reason why is because, well, I don't know Angular, but the other part. Is that, this does, it adheres to the TC39 subscribeable interface and everything like that. So media service is already an observable, you could plug it into RxJS, it's going to work exactly the same. And in fact, in spelt, if you have this media service, you could just read the states from that. So I think it's like something like state equals media service. Or however you do it in spelt. Or, yeah, something like that, because it is subscribable and it's going to work pretty well with, any RxJS solution.
And then, math or no, Matthew was just a comment Chris, do you want to ask her a question? Yeah, so I was basically curious if the media service that you created in line 49 and the machine that you created in line 58 to other like the same instance. And will. If it will, events in React app will be picked up by this media service and vice versa. Ah, okay, so no, these are, these are completely different, and that's a good point to talk about, too. The media machine is like a blueprint for your machine. It's like, Hey, if you were to create a live, living version of it, here's the blueprint of how it's going to work. And so, by doing interpret here, this creates an instance of that, and so useMachine internally is also going to interpret the machine, so this creates a completely new instance. So they're, they're completely separate from each other. But yeah, if you did want to use the exact same instance, then, you would basically do.
Like just any other like data passing solution, for example, in React, you would use context in order to do that. You know, we could even, I mean, this sort of goes against the rules, but we could say, like, const is playing equals useSelector. And I'm grabbing this media service from the outside now, media service. State, state.matches playing, and so you're going to see that, well, if I log is playing. Now, it's grabbing it from the outside. And so we could also say cons, or, you know, let's even do this from the outside, too. Consent equals media service. Dot send. Again, I don't recommend doing this, but it works and. The the reason why is because it just becomes harder to test if you're not passing it in via props or context. So it's gonna be a little bit of a nightmare to test. But that goes for anything with React if you are using external values inside of your components.
But yeah, so now that refers to this service and not the one that's created. In here, so thank you. Yep. [Music] any other questions?
43:00 We have start player and stop player and so that
All right, awesome. So, let's actually make this, do something. Because, okay, we're going back and forth between playing and pause. But like, you know that doesn't really show, like, you know, the benefits of why you would use state machines and everything. So I, I actually wants to talk about, effects. Effects are something that, you know, we typically, push to the side and stay management. We're like, okay, you know what, this is great for, just changing state and everything. And then, if we have to, you know, execute an effects, you know, just throw it in middleware or in reacts, throw it in a useEffect or something, but with XState, effects. Are first-class citizens. So, you, you could even, like, just declaratively state which effects are supposed to run, inside the machine definition without actually providing the implementation for that. But before we get there, let's go back to our machine over here. You know, we go back and forth between playing and paused.
And something I'd like to say is that effects are so important and should be first class, because without effects, your app is useless. It doesn't really do anything. So that's why we have a notation in state machine notation where you would say do, and then you would just say what you're going to do. So I'm just going to say, start player. And so this signifies that, you know, that's that's an effect that should be done. I'm going to make that green and so in pause, and so, you know, now with that, we're in the playing state. Remember that we also have that fave event, so I'm actually going to stretch this out over here. And actually, no, that favorite event is there, so we don't really have to do anything there. I, I just want to show you that, like, we have these actions up here, and these actions occur on the transitions.
So, basically, when you go from paused to playing, this darts player action is going to be executed. And this is important because even though there isn't a transition, for play on playing, which I mean, there shouldn't be like there's nothing should happen there. I'm just going to add it anyway, and so I'll show you that play. We don't want to start the player if we're already playing and the user hits play, you know, a million times for no reason. So, that's why we don't want to tie our side effects to, you know, the actual button. And so what I mean by that is, we don't want to do this. Sent I play start player like this is something that we typically do, and even worse, I've seen, like, you know, we would have a, fetch something that then do something else. So basically, all the effects are happening inside the event handlers. And one of my favorite things to do when I see this is.
If it's a button and it's not being disabled or anything, is just click that button multiple times and see what happens. You're going to notice that the fetch calls are going to be called a lot, you're going to get a lot of unwanted behavior. And this is also exhibited in many apps in many different ways. I'm sure you've been to an app where it says, please do not reload or exit this screen, otherwise bad things are going to happen. You know? Or please don't click this button more than once if you know you're submitting a payment. And I run into it. Even like as recently as this month, where if you click a button too many times because you think the app is frozen. It's going to have unwanted side effects. So that's why it's good to visualize and manage these side effects in a declarative way. And so these are an example of like, doing these effects in, in these transition actions.
So, I'm going to go ahead and add those effects right now. So play target playing, oh yeah. So one thing to add, too. There's also three types. Or three places where you could put effects, you could put effects on the on the transition itself, you could put effects on the entry of a state, so I could say entry. Oops, start player and notice how I'm just specifying it as a string, or you could specify effects, whenever you leave the states, so on, exit, stop player. When you're modeling this, I would always, almost always recommend you start with putting it directly on the transition. And the reason why is that? Let's say that, you know, you put it on the transition and you have another transition over here that comes from another state. And you see, like, okay, I also have to start the player here, and if I copy this and I have another transition now, I need to also start the player here.
And you start to notice a pattern, you see that every single transition that comes into the playing states starts the player. It does that action, so what you could do is you could dry things up and say, okay. Instead of that, I'm just going to have this be an entry action. And so using entry and exit actions are basically a way of just cleaning that up. So that you don't have to repeat yourself everywhere. But for sake of simplicity, we're going to put it on the transition actions first. So we have start player, and, I'm just going to put stop player on the other one, so let me just find it actions stop player. Okay, so we play. It says no implementation found for, start player. And I think we're forgetting to, oh yeah, so let me get rid of this. Okay, so play. You know it, it's going to try to execute the start player action, but if you don't have an implementation, that's going to warn you.
And if I pause, you know, we don't have an implementation for stop player either. So, yeah, let's, you know, just let's just make it sort of a dummy class for this. So, let's call this, uh. Like, all right, trying to figure out the best way to do this without getting into anything too advanced. [Music] all right. So yeah, we have start player and stop player and so that. That can be some sort of external, thing, too. Actually, I'm just gonna put it in here for now. So, we're gonna useEffect for here and just do it there and it's never going to change. So, or actually, should that be the best way to do it? Okay, no, I'm going to do it differently, all right. So we're, yeah, we're actually going to get into a little bit advanced material. But it does show you like, you know what? Like, just what you could do, with XState.
So, I'm going to create an invocation, so we're just going to say invoke, and I'm going to give it an ID of player. And so what this is, it's basically something that does, you know, some sort of effect that lasts, in this case, for the entirety of the machine. So this player we could start stop it, and so this player is going to actually control the playing of music, and everything else. So let's see, I'm just going to have a source over here. And um. In fact, if none of this makes sense to you, then that's fine. Just know that there's something else that's controlling, you know, basically what's happening, so send back [Music] receive just because there's no. Actually, you know what? I'm going to backtrack a little bit because I do want to keep it. Simple, especially since we only have like half an hour left.
So we're going to be doing this outside of the of reacts, just to, you know, just to demonstrate, yeah, I think that's going to be a lot simpler. So I'm just going to have a function start player, and that's going to do something in the function stop layer and that's going to do something else. So we're going to have let's interval ID, and of course, there's no interval, so on start player, interval ID equals start interval. Or, is it starting a rule? Oh, said interval, and so, yeah, we're going to be doing something there. And that's after every second. And then, over here, we just, I think it's clear interval. Yeah, there we go, clear interval, interval ID. Okay, so, I'm just going to console..log. Tick, and. This is just so that you could visualize these actions happening. Okay, so we have our media machine over there, and, we wants to provide these actions first.
So I'm just gonna say actions, start player and stop player. Okay, so now you're going to know this. And just to recap over here. When we're playing, yeah, so when we play, that's going to run start player, when we pause, that's going to run stop players. So if we play here, yeah. Now you can see, it's ticking every second. I should probably just do, like a date.now or something, just that it shows in one second intervals, just like that. And so when we pause now, you notice that there are no more text, so when we play, it's going to keep ticking when we pause. You know, same thing, so, I guess if you wanted to do this inside of your, you know, machine, you might have like a separate media player clients that you're using. But you could also add those actions as a second argument over here, so we could say actions dark layer, stop layer.
And so now we don't really need these here because they're over there, and so let's also console.log state.value, and I also want to show you state.actions, because, this is why we have those declarative actions. Right now. We're in the paused state and nothing is happening now. When we play, we see that there's one object in that array and it's a type Star player. It has an exec, which is the implementation, and so that's basically telling the interpreter that's what should happen. You know, when we start playing and so same thing for paused. When we click pause, it's going to stop the player, and so, you know, the ticking is going to stop, all right. So, now, how to actually feed that back in, to the machine? You could do it either as an external event or you could handle that internally as well. And so that's, yeah, that's going to be a big topic for the next half hour.
But first, I wanted to pause and see if there were any questions about, about the use of actions. All right, so no questions, and again. Something that I wanted to point out is that when you play, you know, let's say I keep playing play because I'm in the PlayStation. I don't know if you can see, but I'm clicking this button furiously and nothing bad is happening. Like, we don't have the states changing. Everything is working as normal, you know, even if I click paused a lot. The state is only going to change once, and this action is only going to execute once because we're following the arrow and we're executing this action.
56:00 If we click play, see, it turns into the pause button
So, yeah, at this point, we're going back and forth between this excalidra and this, to sort of visualize, you know, just exactly what's happening. But instead, I wants to bring in X8 inspect to show you that we could actually inspect these machines in real time. So, yeah, let me just do that real quick. You would import, inspect from XD, inspect and then inspect. I'm just going to say iframe false and we're going to use the new visualizer to do this. So URL, Stately..ai, slash, biz, inspect. These are going to be default options soon, so you won't have to, type all of these at once. But I put iFrame false because if you have an I-frame it's going to show there, if you don't, it's going to open in a different window. And so once you have that set up and you set dab tools to true, check out what happens. So I printed out event listener.
Interesting, let me reload. Maybe it doesn't like me for some reason, gonna reload this. If not, let me just go to 0.401. Let's see if I did anything wrong. Inspect I frame false. Hmm, would this be full string or false bullet? Oh yeah, how did that happen? Okay, sorry about that. Okay, so, thank you for catching that. By the way, I would have never caught that. But yeah, so now you have paws playing and these things are, awkwardly there. They should not be all the way up there. But, I think it's because I have a few things here. We're going to comment this out for now, so that's just a little number. Okay? So, yeah, we have play and we have pause, and so if we play this, you? Could see that it goes to this plane states, and if we pause it, you could see that it goes to the paused state.
But what's cool, too, is that you could click playing over here or play over here. And it's also going to go to the playing state. And you can see that it's, it's ticking away right over there. And yeah, so you know, you could go back and forth between these two, and use that to visualize your machine in real time. But yeah, so that's using the inspector, if you wanted to use that, but let's actually make this a little bit, you know, more interactive. And I'm just going to, disable the inspector for now, just by commenting that out so that we can get back to it. But yeah, that helps you visualize, like, what's going on in your app. It also shows you, like, just what's going to happen? Just like our state machine over here, what's going to happen when certain events, you know, cause transitions, like which actions are going to happen, and things like that.
Yeah, any questions about that, all right? So, yeah, let's get some more exciting stuff. When we're actually like, working with, this, uh. You might have the requirement that. We want the pause button to show when we're playing, we want the play button to show when we're paused. And typically, we would do a bunch of boolean logic, to be like, if is playing, or if is, if not is playing, then show this button, etc. But really, we wants to think about the intent of why we want to disable or hide, or show certain things. And so in the case of, in the case of pause, we want to show this pause button. When we can't play, because obviously you can't play, you have to pause, same thing with the other one, you can't pause, you have to play. So thankfully there is a I'll add this here. There is a state dot can method, and so basically it says, if you can, if you can't play, then, then show the play button, so, state dot can pause.
Show the pause button. Because it makes sense that if you're not. Able to do something, then why show that button? So now if we click play, see, it turns into the pause button. If we click pause now, it turns into the play button. So what's great about this is that you could change your logic however you want. Here, let's say that you want the play button to always work, now that play button is always going to show. Because of that logic. The State.Can method is basically saying, can this transition be taken? Like, for example, play in this state? If we're in this state, it can't, so it's going to hide. If we're in this state, it can, so it's going to show. And so, yeah, that's one of the benefits of, of doing it that way, all right. So, now I want to jump into something a little bit more advanced, which is actually, manipulating this, the context over here.
And also dealing with external services. Because likely, you're not going to have all of your logic inside a single machine, and you're going to have to interact with third-party things. And so with XState, everything is an event, so if you're communicating with a service, you send it in events if they serve it, or some service or some other third-party thing is communicating with you, it's sending you an event. And so internally we could invoke these, you know, these different. They're called actors, which are things that you could send and receive messages from.
1:02:00 All we do here is clear that interval, so clear interval…
And so I'm just going to call this, player like this is the media player that controls, the time and everything. And so we're going to give it a source and we're going to use what's called a callback invocation, so, with the source, it takes two arguments. Which is the context, this stuff over here, and the events, which is the events that, you know, that was passed in when you, you know, got to this invoke this. Evoke is on the machine itself, though, so you don't really need to. You know, the event doesn't really matter, in fact. Yeah, all right, so the context does matter. And so with this callback, you have two arguments you have send back and receive, and so, this, this is actually really. Really flexible. So if you want to just like, spin something up quickly, using send back and receive is the way to go.
Now we're going to be using these, start player and stop player functions, so I'm just going to bring them up here. And so, yeah, actually, instead of using Star player and stop player, we're going to be more methodical about this. I'm going to have the interval ID over here, set interval, and it's going to keep ticking, and then I am going to, return a cleanup function. And so all we do here is clear that interval, so clear interval, interval ID. And actually, now that I think about it, uh. This invocation should only happen in the playing state, because obviously if we're paused, then we don't want this player to send us ticks. So, now, instead of those actions, I'm just going to get rid of those. We're going to see the difference between using an invocation, which is this, and using, actions. So now when we play, you can see that the ticks still happen.
And that's because we're invoking this, this actor which is setting this interval. And so now, when we get out of the state and we pause, no more ticks happen. Okay, so now how do we actually communicate that back to the machine? Well, we can't assign or manipulate context directly. From here, we have to send it an event, so instead of sending it console.log. Tick, we're going to, I'm going to use this first argument here, and we're going to send back [Music] type tick. So now let's handle that over here. We have pause, but now we have tick as well, so we're going to assume that each tick is a second, and so whenever a tick event happens. We're going to decrement this duration, or actually, we're going to increase the elapsed, we still want that duration, but we're going to increase the elapsed by one.
1:05:00 Elapsed just to see what happens
So actions assign and we're just modifying the elapsed property. So, just like, just like this function over here. We get two events, or, sorry, two arguments, the context in the event, we want to return the or, we're just going to return the, context.elapsed plus one. So now I'm going to, uh. Log ST value and state dot context dot. Elapsed just to see what happens. So we press play, you can see it's incrementing, it's going one, two, three, four, five. Press pause. Now, remember, elapsed is five. So when we play again, now keeps counting up. So then we just have to do a little bit of math here and actually show this. I'm going to grab console or const. We're going to get the duration and elapsed from, the state.context, and so now we're just going to show duration minus elapsed. And you could pretend like, that's the song, like, how many minutes is left in the song?
Or actually, I don't think songs work that way. I think it's like, just, you know, x out of, you know, 300, I'm not sure, just pretend it's counting down. Maybe this is just a fun, funky media player, and actually I'm going to do. I have a little function that I copied from stack Overflow format MSS, no idea what that stands for, but I'm going to use it format MSS. And I think all this does is translate these seconds into, like, a minute second format. Okay, cool. So we press play and you can see it's going down, so now we press pause. It's paused at 454 and then we play again, now it's 452, 451, 450. And yeah, so, we avoided, like, adding all of those, you know, extra actions. And instead we have everything contained inside. This invoked player which is only doing two things. It's sending back a tick, and it's also, just clearing that interval whenever we get out of the playing states.
So any questions about that so far? No, no questions, all right, cool, so I'm sorry, sorry, go ahead one. Uh. What are your opinion on putting, like, an observable chain into an invocation function and returning a function that unsubscribes?
1:08:00 We play, we press, skip, and so now it plays a…
Is that the valid use case? Yeah, in fact, I don't have RxJS in here, but if you really wanted to, it's as simple as this. So you could say source. And of course, you get your contacts in event two and you just give it some observable and that's all you have to do. It's going to take care of subscribing and unsubscribing and just listening to? Those values, but the only caveat there is that you want each one of the values that it admits to be event objects. So you would do like something like pipe and then map, if I'm remembering this right? So let's say that it's some sort of number. You would just convert that to type like, type, hey, I don't know well, whatever event type you want, and then value N or something like that. So that's what you would do with observables. And it works natively with X data as well. So cool, yeah, yeah, you could definitely do that, trying to do kind of, analogy here.
The inbox will work similar to the effects in NGRX effects. Yeah, so I don't have too much experience with NDRX effects. But yeah, so this, yeah. It basically runs while you're in this, sorry, not in that, but in this playing state, and so it, you know, exits when you're out of it. So if that's similar to NGRX effects, then, yeah, also like a React analogy. This would be the same thing. Almost the same thing is if you were using effect. And like, you had the state dot value, and you say if state dot value equals playing, or, sorry, if state dot matches playing. Then, you know, do the ticks over there, and then if it doesn't, then, you know, clean up. So that would be pretty much the exact same thing, except now it's built into the machine instead of you having to manage it elsewhere. Nice, all right. So if there are no more questions, let's, let's add a little bit more functionality to this.
What I want to add is, the yeah, while we have 15 minutes left and I'll do this real quick. But I want to add this skip functionality. Just to show you another reason why you would want to use state machines and statecharts for modeling this type of behavior. You know, with something as complex as a media player. So, we're going to just say that when we skip ahead, it's going to, change to a different song, so I'm just going to, just for simplicity, we're going to change. Elapsed to zero, so you're. Going to see this, just shoot back up and so pretend that means we're going to a different song, so let's see. We have playing. We have paused and we also want to implement skip, so go ahead and do that. So when we skip, we don't actually want to change the state, so we're not going to have any sort of target here. And remember, this is on the root of the machine.
So all we want to do is assign, we're going to assign elapsed to zero and see what happens there. So we play, we press, skip, and so now it plays a new song and keep, keep know that it's still playing. So that's, you know, that's a default behavior. If we pause and we skip, you know, it's still paused. So and so, yeah, that's how easily you could add a another, you know, another event. Uh. But something that I thought was pretty interesting, especially when playing around with this in the in the car interface. Was that when you thumbs up a song and you're playing, like, Okay, it's it's fate? In fact, we could probably. Yeah, let's just make that clear. So I'm just going to add some opacity over here, so style equals opacity. And we have to pull that from date, so fade 0.5 or 1., and so we're going to do the same thing for this one right here.
If it's faded, then one, otherwise 0.5. And so now we're using that data to show. Well, obviously it shows like none of these are failed yet. But if we clicked here, then, you know, you could see that it's fade, etc. So yeah, that's just one way of using that data. Um. But something else that I noticed, too, was that if you unfave, it means you don't like the song, which means you really don't want the song to keep playing. So, what you could do if you want to add multiple actions? I'm just going to make this into an array over here. And, I'm going to do the same like skip thing. And I'm going to put it, oops, put it over here as well. So now we have two actions happening and you, you might assume like this might do something. Else, like, let's say that instead of just assigning, we also want to, console..log.
Skipping song so, let's say we were playing and we press here, it's gonna say skipping song. Like, you might notice that, you know if something shows up, like a toast or something, that could be an example of an effect. But now you're like, Ah, okay? So I guess I have to copy and paste this over here too. Because if I unpave something like, let's say I'm playing it and like, I don't like the song, go to a different song, it also needs to skip the song. We do have a lot of duplication here. So one of my, actually favorite things to do is, and like little techniques that you could do in the state machine is. You could say, I want to send myself an event and basically tell myself what to do. It's like giving yourself a to do, or like, Hey, remind myself to do this in the future, you know, just like you would do, or maybe that's something that only I do.
But anyway, what we could do is say instead of instead of just like copying these actions, we could raise an event and say skip, so we're assigning fade to false, but we're also sending the machine itself in events. And so now it's going to do these actions, it's going to send itself a skip event, and so now that skip event is going to perform all of these actions too. So let's see if that works. Press play, I don't like this song, so now I press here. So it's going to reset, do the skipping song, not the skipping song, but it's going to skip the song. And and yeah, do all of that. So, you know, we could do it again. Fave Faving does everything that's expected. And and yeah, so that's. That's basically how you would model the media player.
1:16:00 Just like, if you were to talk to your friends and…
Any questions before we, sort of, you know, do an overview of everything we learned. Well, this is excellent, I love this, thank you for this. And I know we are not at the end. But the question that I that I have, is most about, composition, about the machine state. So how come? We because we don't wanna if the app is big enough, we don't want a single machine handling every single state, an action that could occur. We want to split it, but we might want inside that splitting to also communicate with some pieces of other places. Is that something that is feasible, or, or is more about designing the machine in a way that works that way? Yeah, it's definitely feasible, and we sort of got a taste of it today. With invoke, so invoke creates a new actor, and so in here we're using a callback actor. But it could really be anything, you could even spawn another machine, which will also spawn other machines, and you could even spawn in a sign.
Even though it's a bit, more advanced, but like with more complex app logic, you'll see that's actually really useful. And so the idea is that if I zoom out a little bit, you might have one parent machine which is here, and that might spawn some other machines over here, remember, like, either using invoke or spawn. And so now these machines can talk to the parents, or the parents can talk to those machines. And if this machine wants to send in events to here, there's. There's a couple ways of doing this. We could either, tell the parents, uh. Just like, if you were to talk to your friends and you don't know this friend, you don't have their phone number or something. But you have a mutual friend, you would ask your mutual friend, Hey, can you tell this friend this? And so that event would just go like that.
Or what you could do is, this parent can give you a reference via a message to that friend. So I'm just gonna make this small just for, yeah, so we, we could say, hey, yeah, here's, here's an eye. I guess I can't change that, but yeah, so, as long as you have reference to, any of these, you know what are called actors, then you could communicate with them, and so actors can spawn actors, and typically the communication is hierarchical. But if you again, if you have reference to them, you could talk to them. And this becomes really useful in, big complex. Applications where you might have many different parts needing to talk to each other. And it's also one of the biggest differences between Redux, because with Redux, it's like having only one of these. But that sort of encompasses all of the logic in that combined reducers. And with here. You could have a mix of local and global and shared stores, and those stores could also communicate with each other too.
There's also an example if you go to the GitHub repo for XState. There's a bunch of examples over here, and I made an example for, Ah, it's React list, so in this reacts list, there's a, uh. I think it's on code Sandbox. I forget how to get to it, actually on code Sandbox. But yeah, it's a. It's a machine that spawns friends, and you could add a friend, change a friend, remove a friend, and each friend is also an individual machine, too. So yeah, this is just an example of, you know how, you would have many machines communicating with each other.
1:20:00 Typescripts can handle right now, so we need something extra…
So great, thank you. Yeah, all right. Well, we have seven minutes left. Any other questions? I'll stop talking for now. How could I have the type things? Uh? The typings are a work in progress, and we're actually doing a lot of work on them rights now. So, two of the biggest initiatives, one of them was Iraq, actually already started. And it's using creates model, so if you use creates model, then, that's going to improve the typing a lot and make the typing experience a lot better. So there's even a whole TypeScript guide over here. But the second thing that we're working on is actually, say, BS code is actually a VS code extension which is also going to be using, what's called a, a type generator. And so as you're typing your machines, it's going to provide you a lot of really nice hints for, like, just properly typing all of your events and contacts and everything. And it's going to be a lot smarter than what you could do with TypeScript.
So TypeScript is one of our hugest focuses right now, and we're working on improving the experience. The problem is that, we're trying to express a lot more than. Typescripts can handle right now, so we need something extra, like the VS code extension and TypeScript. It's just like trying to do GraphQL and have typescripts behave with it. It's hard. Without an extension. GraphQL sort of does things that go beyond what TypeScript is capable of. And so it's the same thing over here. So definitely check out the VS code extension. I feel like it's going to help a lot and keep your eye on the upcoming. We have a PR for, for type Gen, so this big one over here, lots of good changes coming there. And also in version 5, we're going to be cleaning up the types a lot. So, right now the typings are workable. You might run into some edge cases where you need to use any, but for the most part, as long as you follow the TypeScript guides.
It's pretty solid. That's why I think we're coming up on time. Yeah, [Music], that right? [Laughter] it's like, perfect, you fit it in perfectly, this is awesome.
1:23:00 Just like, have a really advanced visual editor for these diagrams
So like, you know, I guess, if there's no additional questions, just talking a little bit about like, XState and kind of like, what should we be expecting coming out of XState? Or is it too early for me to ask? No, no, yeah, so, yeah, that's a really good question. We did recently, or semi recently released this public visualizer, which we're going to just keep working on. This is also completely open source. So this month is HacktoberFest. If you want to contribute to that, by the time this video airs, maybe it won't be October Fest, but please still contribute. You know, PR's, if you want to see this improved in any way, um. But we're working on two big initiatives, which is a registry where anyone can basically create these machines and share them, and, you know, just have like a nice collection of these. So that if you wanted to make your own media player, but you didn't want to write the machine from scratch.
You could look at other people's machines that they made. And say, I like that one. It has all the features I need, and even if it doesn't, it's easy for me to add those features and just. Copy and paste it over to your application. The second thing we're working on is a visual editor. So, you know, XState, it has an interesting API, it's very object-based. And so the reason for that is really to get it playing right with the visualization and also trying to make it as concise as possible. But the ideal scenario is to be able to just visually create this and have sort of a living diagram, where you can drag and drop and maybe add mock-ups. And yeah, just like, have a really advanced visual editor for these diagrams. But the artifact of this not just being a static image, but rather being a living diagram, that it's basically already coded. So whatever you draw is what is reflected in your application.
And, I just think that's really powerful because I've been working with diagrams for such a long time. Where, the diagrams are outdate, or the code is out of dates. Or, you know, things are missing and they're never in sync with each other. So, yeah, we're trying to improve the way that, you know, developers, designers and stakeholders work together with all of these tools. So yeah, we're doing a closed beta at the end of the month, and just slowly rolling that out. So by early next year, expect a public data of the UM. The visual editor. And I'm really excited for it is so amazing. And it's great that your repo is already set up for people to contribute. Cause, you know, I'm all about that. I keep bugging Ben on our XGS repo. I'm like, have little more easy issues for people to actually do so. Yeah, thank you so much and you can follow David on Twitter.
By the way, at @DavidKPiano, it's right up to the top, top, left, right there David's name, so everybody calls him David piano, right, David. Yeah, I guess. Yeah. And you know, keep a lookout. But hopefully everybody starts using state machines and checks out Stately. And, yeah, I really appreciated this. Thank you, yeah, and thank you for having me.
Related talks
-
From Pandemic Pastime to Real VC-Funded Startup
The Work Item podcast (Den), 2024. 31:58 -
Everything is an Actor
React Finland Mini-Conference #2 (2020). 44:49, 11K views -
Putting the "Act" in Reactive: From Observables to Actors
RxJS Live! London, 2021. 38:31, 1.6K views -
Webinar: Get started with XState v5
Stately webinar, 2023. 1:13:11, 11.3K views