Let's Pair Program State Machines and Statecharts
Watch on YouTube (Fun Fun Function)
What is this talk about?
“I always say that state machines are a good refactor target.”
“First of all, you don't need a library to create state machines itself, you could use a switch statement.”
From the opening of the conversation.
Key takeaways
- I always say that state machines are a good refactor target. 3:00
- We could listen to on transition, which is going to give us the state, and so every single time that state changes. 18:00
- All that's happening is that state value, like whether it's dragging or idle, it's going to be displayed directly on the body. 25:00
- We could do that just for now, we could do that directly in on transition, because over here we receive the state context. 33:00
- If since I'm putting all that state on data state, if I say data states equals dragging. 52:00
Quoted from the transcript. Conversations include other speakers.
Full transcript
From YouTube auto-captions. Punctuation and capitals were restored automatically. Technical terms were normalized; some errors remain. 7,938 words.
0:00 Introduction
I think that this is a great, great place to talk about what state machines are, because I think that a lot of people probably are confused about that. Mm-hmm, yeah, so, state machines describes, like, really concisely, it's just it's a collection of states. So, for example, you could have if you're loading something, you could be in the idle, the loading, the success or the failure state. And basically it's it's these rules that tell you how you could go between these states. For example, if you're in the idle state and they fetch events, happens now you're in the loading states. And so one of the rules with finite state machines is you could only be in one state at a time. So you can't speed. Both in the loading and the success state at the same time, or the error and the success obviously compete in both of those at the same time. You're only in one of those states at the time, and you move through those states in a very predefined way, and those are called transitions.
Well, what is the benefit of only being in one state at the same time? Why would you add that kind of limitation to your application, well, in short, its determinism. Take a traffic like, for example, this is sort of might be the hello world of state machines. You would not want a traffic light to be both on green and red at the same time, right? So you want to be absolutely guaranteed that you're only in one of those states. And so by states, these finite states define the behavior of a system or an application. And so you're saying, when you're in this state, this is the behavior that can happen. So, for instance, going back to my loading example, let's say that in the idle state, that is the only state where the users allowed to press, that's your press submits or something. And so we can define that behavior only for the idle states.
So in the loading states, we could have different behavior where nothing happens. We're just waiting for the request to resolve. And just like that, we've solved the problem of. Have you ever been to a forum and accidentally click the submit button many, many times? Or, you know, accidentally reloaded your page? And some unexpected? Behavior happens that is solved by state machines because you could only do a certain set of things in each given state. And so it's not, it is a limitation, but it's a it's a good limitation because it makes your application behaviors so much more predictable. So with a statement, it seems to me that this is. It reminds me a little bit about. Like, the way Redux forces you to think a lot about your, your state, it requires you to design your state in a way. Sort of, yeah, and state machines, to me, all seem like you.
Just. It just forces you to think more about the different states that your applications are is going to be in upfront. Yes, it seems to me also that then H and correct me if I'm wrong. A challenge with that would be that while you have to think about things upfront. And when you think about things upfront, then it's kind of like, hard to play things by ear. It's a lot like the whole problem with upfront design, you know, like this is this good for prototyping? Is what I'm saying. Yeah, yeah, this is one of the challenges where, you know, you do have to design it upfront. However, that's or why I created XD is because you are able to play with that model. And just rearrange states, or add new states, or remove states as you want. But I always say that state machines are a good refactor target. So if your business logic requirements aren't clear, then code it however you want.
And once becomes at this level of complexity where you're, like, Okay, I understand the behavior, I need to organize it now. That's when you start, like grouping these into finite states and modeling it in a more strict way. Because otherwise, without the that, you're coding your app in a way where anything can happen at any time, and we know that's just not true. For example, if it's loading, you shouldn't allow the user to keep pressing submit. You should say that should do nothing, and just having that sort of predictable behavior. Yeah, so that's state machines, but what is what? What is XState in this? In this world? XState is a library that allows you to create steam machines now. First of all, you don't need a library to create state machines itself, you could use a switch statement. Someone mentioned Redux, it's very possible to create state machines, and Redux because state machines are just a pattern.
What XState enables is state machines, and more. It enables you to creates what's called states charts, and statecharts are extended state machines. They have other features, like you could have nested states, parallel states history, states actions. Timers invoke services, all of these complex things where you probably want a library for it, because the key algorithms are very, very, very complicated. And that's part of the reason why it is 15 kilobytes, but in version 5 we are going to bring that size down. And also if you just want finite state machines with XState, there's X8 Slash FSM, which is only one kilobyte, so don't complain about the size. I mean, it really, really, really tiny, all right, so that's that, that's XState. I would like to thank today's sponsor, Brilliant, Brilliant has been responsible for a long time. And violence Org slash FFF. I think it is right. If you go here, you'll get a lot, like 20% off the annual subscription.
Brilliant is a like an interactive learning platform where you can learn tons of different things. But the thing that I tend to recommend is the computer science fundamental stuff. And if you're preparing for interviews, or the computer science math, if you're getting into machine learning. Because that's usually what you run into. And I was sorry, I was just washing somebody's that says, I wash hands and sanitize. Yes, corona. What we're gonna do is we are going to do a very simple drag-and-drop, and we're gonna see how we could implement drag-and-drop.
7:00 Let's, hmm, let's serve this somehow
Which has been notoriously a really confusing thing that a lot of developers would reach for a library for, or something else. And that's if we're gonna try do it ourselves and see just how easy it could be, or easy. In quotes like, yeah, that's an awesome example, because, as people in chat said, it's drag-and-drop is a nasty thing to implement. Generally, it's like, yeah, so yeah, that's it from. Let's do it. So where do we start? Alright, so we are going to start well, let's make sure that we have ayats and styles. So let's, hmm, let's serve this somehow. Well, what's your paperweight to serve this? Well? Actually, you could just open the next email, right? All right, yeah. I mean, in the index dot HTML, what do you eat? Do you want? Or do we want to jump the index touch as well? Hmm, wait, where do we start with? So what I want to do is just make sure that it's actually showing on the screen.
Oh, so, if we could run a server or something like that, and actually with last year, you could share servers. Yeah, that's just such a cool thing with live share. So it was such a long time since I did it. What's a good web server to use nowadays? Do we have, like some? I think, I think what you could do is like, MP, MPX serve, and it'll just let's see, it'll just serve it. Magically, I think that somebody would have written something with that ad is so cool. And PX herb, all right, so let's see 5 B sounds hard. Yeah, yeah, he's great, I've everything. Okay, so we have the box. Ah, forgot the styles? Okay, so link style sheet and I called it style, thought CSS okay. So if all goes well, we should see a yeah, oh, I wonder if served like olive reloads, it probably doesn't.
What do we? I don't save funk. Let's see, let's inspect this. I don't think it's free. Oh yeah, it should be okay. So we have the styles here that doesn't have height, alright, so let's take look styles. Just making sure that everything's coming into Braille. Feeling. Sources panel Oh right, because we didn't actually add styles, I just add some boilerplate Styles that I'd like to use.
10:00 If you divide these into a hundred…
But let's actually, let's, let's make the box visible. And so what we could do is I'm going to be a style that CSS. Yeah, love working in here. So let's just give it a height of like, 20 V min with 20. Be men. And what's what's your favorite color? 99 Missy Z.F.F. For some reason, it's only hex code. I know off the top of my head, you never bother, right? Awesome, alright. So we have a box, what, what it like. Demon is a new CSS property for me. Yeah, so Viewport units are you? Have you port width, which is the width of your entire viewport, your, your browser window, and viewport height is your height? And so if you divide these into a hundred, you get like one BW is one of the viewport width and one VH is one of the viewport heights. And so V Min is just a smallest of those.
So, in most use cases, that would be the browser height, because it's usually wider, but not always, I mean, sometimes on mobile devices, the Wikus smaller. So anyway, this is the Fox that we wants to drag and drop. And so I'm gonna go in Index J. S and let me just a console dot log XE just to make sure it's there. We're loading it via Unpackage, so I just wants to verify I wishes had a library loading. Okay, so it is there, yeah, which is, which is awesome. Okay, and you're gonna be doing a lot of this, but I'm gonna just start you off, yeah. The first thing that we do with XState is. We're going to create a machine, so a state machine, and so that's with create machine, and so create machine.
12:00 In this case, we could just say idle…
Everything is going to go inside of here. Now we have a machine and we have lots of states that go with that machine. So the initial state is going to be like, basically what we start off with in the machine. And in this case, we could just say idle, this is when we're not really dragging the box, like just nothing is happening. And then we have states, and so the two states that we're going to deal with right now are going to be idle. Of course, that's our first statement and dragging, so that's the state when the box is being dragged, fair enough, and yeah, so Niala dragging. These are basically the equivalent of in a game, it would be Mario jumping or crouching, exactly. So I'm gonna call this a drag drop machine and also do something else. This is an old one. My favorite parts of this is you could put it in a visualizer. So I'll go ahead and share that link in the chat so other people could play around with it as well.
Right now, it's very simple, but if I take that exact code. And I put it in a visualizer, then you're going to be able to see the states. Right now, there's no events, there's no transitions, it's just those states in the visualizer. Can you? So you paste that in chat again because I didn't have the chat open on my coding computer? Oh, okay, do you want me the PC on Twitter? No, yes, I just send it again in stream chat. I just lost the chat. Oh okay, no problem. Oh, it says your message is identical to the one that was just that's so funny. Okay, send it on Twitter, so I will, I will make it nominate any. Adding three dots. Did that work? Or their detection is so alright, really. Oh, that's, that's a Larry. Okay, hang on, then I won't duh. There we go and I'll check that so that we can see it on screen.
Oh, there we go. Oh, this is so cool. Yeah, that is really, really funky. Okay, I'm starting to get what people, people like this, yeah, and I am working on improving the visualizer too, so that's going to be coming soon. So you could think of this machine as sort of a blueprint of how the logic is going to work for, you know, for dragging and dropping. So let's think about events for a minute. Yeah, so I could say on and this is going to be in terms of, like some it vents. Earth event and next state. So what we want to do here is we want to say on in the bent, move to this next state, or go to this next state. So in idle, I'm guessing when we do a mouse down, that's going to move us to Dragon. Alright, so I'll let you do that, alright, so and like, on it, okay, so okay.
So these are mmm. And goes down. And then we want to change that to, like, we want to somehow change the state now to dragging. Yeah, but this is I actually. Yes, you could do it that way. There is a way, actually what we would want to do. That's a shorthand for this. Yeah, exact same thing. Yeah. I think that this the shorthand seems to magic to me. Even though it's one of those things that is kind of like when Haskell takes it. Too far, like it just becomes so terse that you have no idea what it's happening. Yeah, and so in dragging, let's, let's. How would we go back to idle? We would probably want a mouse. Ah, yeah, sure, so my up. Mmm-hmm. Then we go back to you idle, right? Or we could do it the non magic way target, right? I agree with you, I don't like magic too much. Yeah. The reason that I, you know, added the stream thing is because, again, for prototyping, it's really nice to just type in the string and then have that all displayed there.
Yeah, yeah, when you guys like playing around, mm-hmm, all right. So, that same visualization. I updated it so you could refresh it and now you could extra just play around going between each of those stakes. So okay, so if I, that's really cool. Mm-hmm. Yeah, that's what's cool. Is that it? It actually enforces the rules, this diagram, so if I click mouse up here now, I can only click mouse up, it's not possible. Like, right, exactly, that's pretty cool, all right. So let's actually make this rule, you know, because we do want to make this box, you know, drag and drop and all of that stuff. So in order to do that, this, this machine again, is just a blueprint. Hang on. We have a question from Korean-American Barbecue, which I actually think is a great question. Does that automatically set up an event listeners? Or do you do that manually?
Ah, no, so you have to do it manually. And that's because I, you know, like you said, I want to avoid this much magic as possible.
18:00 In this case, it's the drag drop service that we're sending…
And you could also have custom events, so you could think of this in sort of a Redux sort of way, where the event handlers aren't set by magically. You have to do it yourself. Yeah, and so, to make this machine alive, we have to create a service, and that's just, yeah. You could think of services as micro services. Where you have the code, where the code doesn't really do anything, but when you actually like, make it alive, then you create an instance of that code. That's service living somewhere. So I'll call this drag drop service, and all we do is we interpret the drag-drop, the. Machine, and this is the only like boiler plate you can all set up for you here. And we could listen to on transition, which is going to give us the state, and so every single time that state changes. We could console. Dot log that's data and see all that's happening there, and we'll go ahead and start it.
What does insert like, interpret to me seems a little bit like a weird, weird word here. Can you explain the logic or it for that naming, right? So all of these come from what statecharts are, what state machines are in the SC XML spec? So I don't really, I don't really invent any of these terms, some, so I probably was in a different term, but interpret what a machine needs to be interpreted, so, like I said, it's a blueprint. And in order to make it actually alive and something that can respond to events and do things, it needs to be interpreted. And so all that this is doing is this creep machine is actually completely stateless like we're, we don't have any internal state in it. And so I could like console.log, drag-drop machine, dot transition, and this is a pure function. So we could say, if we're in the idle states and a mouse down event happens, what's gonna be our next state?
And so if we go into the browser, this other reloads, you're going to see so well it, says. DRAGON yeah, it's basically, yeah, it's sort of like a fancy data structure. The yes critic machine. Okay, actually, it's alright, so I'll remove that, and yes, so basically it's just creating a live version of that machine. So, let's let's actually now map these mouse up, or, yeah, these masks down and massive events to actual events. All right, okay, you do that alright. Map these milestone events to actual events. So we'll probably need the box first, like a reference to the box elements. Alright, school, and that was an idea, so I'm just gonna dump it here for now. Yeah, Coms box don't American keyboard layout document dot get element by ID. Mmm, I call the box that's yep, cool, and then listener, Oh, I can't still code some. This is awesome.
And we had one start with mouse down, then, yeah, and takes a. Function which takes an event. Mm-hmm, ha hunt, that's some magic kept in there, let's see cool. And right now we want to send that events to the drive drop service in weekend, we could actually send that event as is. Because may the browser events already have a type on them. So if you think of Redux, you know our event objects that. It's like, yeah, and so that's going to be service dots and the events goes there. So in this case, it's the drag drop service that we're sending that events to. Okay, don't do so, Jack drop service is our sort of events, like our actual states Tracker. Yeah, yeah, exactly, you could think of it that way, and so we've just send the events directly to that. And yeah, so, like, whoops. So if we just send mouse down here, mm-hmm, yeah, that will work.
But, and so, yeah, if you if you now look at the console of the browser, you'll you'll see a change boom as you put your mouse all right. So now, yeah, okay, I see it actually here, that we now see that it, it now changed. Dragon, where did you have the oh yeah, yeah? So this is from here, their own transition handler. This is a really, really handy, handy way of debugging applications because this would require quite a bit of like. It's just a nice way of tracking what is what is happening. Mm-hmm, yeah, so let's look one for mess up as well. Yes, let's do it so into so one. One part of me, one part of me is like, now, I like that. The framework is not afraid of this boilerplate because the duplication here is something that would make some people go like, Oh, no, this is boilerplate.
24:00 Cool, so dragging Idol, Dagon, Hydrofracking Idol, yeah…
But the nice part is that it's also explicit. You can track it if we just remove these and figure out a way to remove, automatically remove these duplications. With a lot of frameworks, you, you end up with magic and it's impossible to understand what is going on, right? Anyway? We have a mouse up event. Cool, so dragging Idol, Dagon, Hydrofracking Idol, yeah, and now if I hold down the mouse, it will be dragging, and if I let go, it should return to idle. Yes, brilliant, yeah. It's easier to see in the actual browser that this is just for fun. So I'm using the data sets have used, I'm sure you've used data set before. It's super, super useful to strings. You don't have to worry about this. All that's happening is that state value, like whether it's dragging or idle, it's going to be displayed directly on the body. Like you said that you probably use data sets before, like you should have asked me if I use data, said before.
I am NOT like, because I mean, I'm a YouTuber. Nowadays. Sound like a text, you analyze everything like a lot of times it what it is. It are like some kind of key value store that are built into the browser. Notice. Oh yeah, so um. Data attributes are attributes, where you know all HTML have attributes, but if you wanted to find your own attributes, then you could do that using data attributes. Hmm, and so the data set API allows you to interact with that using just JavaScript. So, but it's not showing for some reason. Oh, I love that, Robert Abel says. I've never heard of this. Why do people ever pay me money? I feel the same way, Robert able, so I feel the same way. I know, okay, so mmm, okay, okay, but now all rosy, for some reason, all right. Do you see the if you reload your browser?
Do you see the status in the right? Yeah, I do what I need to resize this window a little bit, the audience wants. And Emeric, Oh, wait, oh yeah. So, one common problem, and this is something that I've spent hours, I'm like, just trying to figure out. With Drag-drop is that you'll listen to mouse down on the actual events, but mouse up, you want that to be on the container. Elephant yeah, comment. So, in this case, you might want to listen to Mass upon the body instead of on the element. And that's not to be important for mouse move as well, because with the browser, it's a little bit weird. But when you move your mouse or your pointer device, sometimes it could be faster than the element moves, which means your pointer will escape the elements. And then some that you're no longer dragon, which is a really, really frustrating.
Thing so yeah, yeah, you got it, yeah. So now we have a body of endless ER and so just make sure that works. Cool. So so now we're going between dragging and idle, and so that's working pretty well, you know, brilliant, alright, so, you know, now we actually need to grab this and attach it to the mouse cursor. I suppose, so at least that's what I like. What's a good approach to do that? So my approach, I really like using the native event, so instead send mass down, I'm gonna send events.
28:00 If we do client X minus context, that X…
And this event is going to include like a Penstock white X, which we could use, and also events Dodd's clients Y. And we could use both of those. And really help out now. One one common criticism of state machines is that it's just finite states. And what if you had to actually represent something that's, you know, a little bit more infinite? Such as extended states? Yeah, and so this is this is a core concept to statecharts in, it's called extended states. In the next state. I call it context, because it's like a contextual states. That's sort of attached to this date and so I'll just set this up. We could have pins like X 0, Y 0, and these are going to be like just our pointer positions, like when we click. That's what we want to keep track of. And also we might want to keep track of DX, which is how far on the X axis we've moved in DY, which is how far on the Y axis we moved.
I like, I think we're like jumping a little bit ahead because I don't understand why you want to track that at the moment. Oh, okay, well, we do want to make it move. So all right, yeah, but anyway, like, Oh, I kind of wanna just enjoy it. Before, like I, I was thinking of Boop, I was just thinking about drawing the thing at the right position right now, right? So how do we get these contact? How do we update these context parameters from the client X and client why? And how do we get them out to draw them on the screen? Question alright, so in order to do that, we have to assign to this context, and so there's. An assign function that represents an action, and actions and state machines are side-effects. Ah, and so did. This would be a side effect, alright, so how do it? When?
How do we trigger that side effect? All right, so all side effects are triggered due to events, in this case. Mast down. We probably wants to track where that, where that pointer is, so that would be in action. Yeah, so okay, so that's actions, yeah. And does a sign give us, like, some object for that? Yes, a sign gives you an object, and all this object does is. It describes how you're supposed to update the state and so you could pass in a function that returns to the next state. So okay, so okay, okay, so this wait so I can give this a function. Yeah, you could give you the function, okay, cool, and the function. And this is gonna give us the mouse event. It will give you the mouse event as, so it gives you the current context first, okay, and the mouse events as well. Yep, and with that then, okay. So I miss like, like this would be like the Navy way to do a bit.
I'm not like the seems like it wouldn't work, but mouse event of client its would technically work. Oh really, yeah, it will technically work. You're mutating context, which I mean is, yeah, secretly okay, but you know, obviously you should try to return like a new context, like, no, should we do that or not? Oh so, yeah, you should try to be as immutable as possible. So instead, this context. EXON Oh yeah, yeah, so we played a lot of context, something like a little and I, yeah, you got. I have done Redux at some point, at some point in my life and this. And then we want the X to be that. And then why, you know, massive and its dot find why? VinCenT all right, yeah. So I went ahead and I logged the. So we're logging the context in the console and so we could see what happens in the browser when we actually do that. Oh sweet, so now, okay, now I think I know why you want to the distance.
Yeah, so we are, just because we are just logging the position at the. Time of driving we are not constantly updating, and when dragging writes, Okay, cool, so now we have, we now have the mouse event, updating the context. Mm-hm. But how then do we get the ball to actually use that state? Oh, via the box. So we could do that just for now, we could do that directly in on transition, because over here we receive the state context. And we receive those XY values. Now, we're not going to use those X, Y values directly, because that's just tracking where on the box we clicked. What's going to be more important is those DX and DY values, or how far we dragged from the original points. But let's make the mistake first, so that we otherwise I won't, truly otherwise I or the audience, I won't understand what. Albert, why we're doing things so I.
This means that we have a state and within state we have access to the context. So I'll, yes, do you like box dot? I don't know, how do you do this in? Like, top X or something? No, Oh God. Oh. Style doesn't property, I mean, it's only opposed. Set properly. And then we have, well, what is it? Top X? Top topics? Let's let's let her roll X for X, right? Or it's just left, sorry, just left. And then, yeah, yeah, oh God, I'm so broken today. All right, the context, it's a like it, no, my choice is always on Monday, but like, this is Monday morning, man, okay, state of context. Dot the decks, yeah, and we might add pixels. Cool, alright to see. That's that. No. Cannot access box before initialization. No, of course, not put it there. WAP cool, all right. So now the X is, X is working.
Yeah, oh yes, okay, it's moving. Yeah, cool, I'll do that with Y as well. Okay, cool, yeah. So now, whenever you click, that's where the box is going to move. Which isn't exactly what we want, but it does demonstrate out these values are updating the box based on the state change. So all right, so that's good, cool. So now we want, want this actually, because it's not actually moving following the cursor now that I'm moving right. And so that's what that DX is DUI, our force, so we might need. To do a little bit more math, and let's have another, another event just to do this. Because we forgot to add mouse move when we're actually moving mouse. So again, that's something we're gonna want to add to the body, so let's do that. I'm just down here. The body dump event listener mouse move [Music]. Hmm, right, and then I supposedly, what?
Like? We want to shove this into the drop service? Yeah, the track drops and we just send it directly. So this will give us access to the to the states inside. Yeah, and then on. When we are dragging, and only when we are dragging, we want get access to, we want we get a mousemove event. Mm-hmm move. Yeah, God, there we go. Yeah, no, but this is a we want to function, right? Oh, no, no, so same thing. You wanted. Objects where you have a target, and this target, since, you know, we're still dragging, the target is going to be exactly the same. So we're just gonna say target. Yeah, dragon, that's worse still, dragon. And now we got do a little bit of math so that same actions. We could probably copy and paste the one at the top. Because we're going to be updating DX and DY now.
And so that's to get how far away from the original points. The mouse actually traveled so that we could use that, and so now we could change DX and DY. Okay, d why? But we need to do some like subtraction here from the X and contact, yes, so context dot X, let's see. - yeah, like this is one of the things that is just easier. Just see, yeah, but this. But we'll see if we do it the wrong way. Yeah, like it probably is gonna be. Intuitively, I think it's gonna be. Plus here, I don't know. Let's see. Yeah, well, we'll play around with this and see what happens. All right, let's see, okay, but now we also need to use these. Yeah, yeah, actually, we can just see in the console though. See here. Yeah, yeah, ah, nice, nice debugger. Okay, so I'm dragging to the right now, I'll start dragging on EDX.
Okay, it's the wrong thing. Like it's because it's getting its, its - now, and it should be, it should be. Positive Chiba name yeah, right, so now change this to plus, now debug it, so now it's correct. See with Dys. DUI is right, though, because I'm dragging down and then DUI is turning negative. It's a yeah, do you want it that way? Though? No, what, I think, so, so I think, hmm. If we do it the other way around, like if we. If we do client X minus context, that X, I think that's didn't work context - so clients - context. Oh, okay, let's try that. I honestly, that's one of the most confusing parts for me - but it's one of those things where if one way doesn't work, then it's probably the other way. Yep, okay, you know, if you feel some people correct values.
Yeah, sure, yeah, yeah, that works and so, I guess now we should style using those DX and DY values instead of B instead of the X and Y values. Mm-hmm.
41:00 [Music] speaking of Matt, like, so there's this weird behavior…
So wait, they need. We need to use both, right? We need to subtract, subtract. The oh, no, because, because all we're doing is measuring distance. So DX just represents how far away exactly. Yeah, yeah, so we could use just that, just DX like that and Dy like that. Okay, I like, it doesn't make sense to me. Yeah, but so basically, if you drag all right, so we're getting the exposition, which doesn't matter where that position is, that's just used to track a part. So we move ten pixels to the rights, then let's should be 10 pixels, regardless of where it is. Okay, okay, so we set the property to the distance. Mm-hmm. I think, yeah, yeah, okay, yeah, yeah. So it's constantly update, Okay, yeah, that's okay, that's, that's funky, but okay, I got it. Yeah, yeah, I am. Esmi points out that Marcin is currently on body rather than box, but that's by Sammy and by intent.
No. Mm-hmm, yeah. So that's on purpose, because if you move your mouse really fast, sometimes it will escape the elements. And so you want to be keeping track of that mouse position in the bigger container, because imagine if your element moves really slow compared to your mouse, you're, you're no longer going to be dragging it, right? Cool, nice, someone said too much, Matt, this is great. School addition and subtraction. I don't know how that's too much, Matt, but it's it's fine. It is like, I think that it was me being. It's too much math for a person doing, doing streaming. Now, I'd find, ya know, it's not that complicated, it's just something that, yes, it's kind of math that you need to get after you play around with a little bit, right? Yeah. [Music] speaking of Matt, like, so there's this weird behavior, of course, that you saw that when you click and then you click again.
Now we no longer have, like, the box is no longer under us. So I have to think about how to do that, like when we click and then when we click again. Now we're going to be, yeah, somewhere else, so so we have to keep track of those values somehow.
44:00 We have XY, pointer, X pointer, Y, DX and Dy…
Oh, all right, so okay. So so bring me in a little bit. Here we right now. What problem are you solving? We are we're looking at like right now. I, I can't drag the ball. However, if I start dragging it again, it jumps up back to its original position. Yeah, and why is this? So? It's because when we go back to the idle state and then we click on it again. Now we get a brand new X and Y position, and so even though the elements has moved, it'll be like that brand new XY position. Will say, Oh, you only moved it, you know, ten pixels, where in reality it's probably moved 100 or 200 pixels before that. So my guess here is, what if we take the previous way? No, no, we can't do that. Why not? Well, because then it's gonna keep adding on itself and it's gonna go, like, exponentially far. So I have an alternate idea, though, I have a plan, and that plan is. It might seem silly, but using six variables instead of four now.
Because now what we want to do is I'm going to track. We have XY, pointer, X pointer, Y, DX and Dy, so the X, Y. These are going to be the position of the box. And the pointer axis is going to be where you clicked, and the DX DY is going to be how far from where you click. And now we have, like Phoebe's variables. To store where the actual boxes. And so we could update like on mouse down. We'll set it to pointer, X, in point or Y instead, and so we just need to update it below as well. So, you lost me a little bit, all right, so what? We're tracking the DX and Dy, those are how far we traveled from the pointer, so not the X and Y. The X and Y. We're tracking where the actual box is. And so. Card. Okay, we want to change this to winter and pointer Okay, you know what your ex point?
47:00 If we have body data, state equals dragging, hmm…
Y? Yes, and so now all we have to do is one more thing over here. Where when we, when we put the mouse up. We want to change context X in context dot Y to be the new values, which is those DX, E, V, Y values. Okay, so we're basically committing that change. Ah, okay, let's see how do we do this. So we did. It's called actions, these are side effects, and you do, then the side effect is a sign. And the first argument is context. Mm-hm, and we don't need, we don't bleep religions, have a second or arguments here thing. Yeah, because it's idle, no arguments. And we'll have was, do we want to assign the initial ones? No, wait, yeah, X, oh yeah, we want to do. They were chanting and they object assignment. So do the contexts. Mmm, and we want it at Sun X2, like, are these initial variables? Or this?
What? But what do mean like this? So the X we want to change to, for example, context DX, because how far it moves, like, oh, sorry, I'm into context X plus context dot DX because it's wherever the original position of it is. Plus, how far removed? Okay, yeah, so that's honestly. One of the most confusing parts about drag-and-drop is just all the math involved. Which it's not that bad once you think about it, but you know, it does get a little bit annoying. So let's see, okay, so let's see well, so water. We want to reset the other values to, so we wants to reset the X to 0 and DY to 0. What add the DX? Yes, yeah, yes, 0 and Dy to 0, right? So all right, stepping back. And thinking about how this is going to work now, we're measuring two things we're measuring where the box is and how far we moved the box.
So, in other words, left is now going to be staked out. Context dot X plus P dot context at the X, so this is where the box is and how far the box and moved. Hmm. And so we're gonna do the same thing for the other one I don't like. Can you show me what it is that you wanted me to do because I was not on the screen when you did it? Oh, state our context dot y plus I all right, brilliant, okay. So what we're seeing here is that, oops, all right, cool. So this is the state is now always, constantly, whenever we have a transition and transition. [Music] what? I'm so on transition, mm-hmm. To me, like, it seems weird to me, like that. The the box is constantly being updated on the transition. Because to me, like, is, is it sort of like it is it?
Thinking of transition as a dragging like to me, transitions is just strong stitches between states in my mind. Yet it's still being updated. Yeah, yeah. So, a state being changed can be its finite state change. Like it's going from idle to dragging, but also the context within that states changing as well, so both of those things say it's like a state name dragging, plus the context of the state. Okay, that's that's transitioning from them, except it makes sense. Mm-hmm. So if you play around the box like, it actually works, which is awesome, whoa-ah is pretty cool, mm-hmm. And a lot of people might be looking at this and saying, well, I, I could have done this just, you know, using functions and is dragging or things like that. But because we have access to that finite state like Idler tracking, we could actually add some cool Styles based on, like, whether it's dragging our idle.
So I'm gonna jump into the CSS just to demonstrate this. Yeah, real quick. So if since I'm putting all that state on data state, if I say data states equals dragging. And I target the box, I could give it a let's give it a background of red. And so now you'll see. When it's when it's dragging, its gonna change color. This is really interesting. Ah, dad, estate, we're like, Oh, okay, look, can you explain to me and other people that have not seen this before? The data states, Ah, alright. So Den states that is an attribute, it's the wrong thing. So if we have body data, state equals dragging, hmm, so it doesn't attribute that we add to the body, and that attribute is called a data attribute. And what's really cool is that in JavaScript, you could just say body dot data sets that states, equals, whatever, and that's automatically going to set that data. Okay, it's, that's what it is.
I just like, didn't connect, connect this, which makes, I think I've actually have used it before, I just completely forgotten it. It's so useful. Yeah, yeah, so this is what we're doing, and so that's what we built, why we're doing this.
54:00 Dragon dropping becomes complicated, very hard…
That's funky, that makes a lot of sense, so then we can style based on that. All right, cool. Mm-hmm. Love it, yeah. So, one other cool thing, just probably. One last thing I want to show is by representing all of your seats. In this way, it becomes so much easier to add functionality or even remove functionality. So won't one do one more thing? Let's, let's do it. We are over time, but like, let's, let's, let's finish. Okay, let's finish, like, doesn't know what? No, let's not do it. I've made this mistake before. Yeah, I think that we, I think that you've really did, like, we've really demonstrated the capabilities of this. I don't think that this is all that complicated. I've implemented drag-and-drop schemes and it's it becomes apps will be nasty very quickly to get a structure that for it. That makes a lot of sense in this that is this clean for this little code.
I think it's it's fine, it's really nice. Yeah, especially like Burns, you started like adding position, locking the state, and like locking the positions to things. And yeah, dragon dropping becomes complicated, very hard, so any structure is really nice. Mm-hmm. And I went ahead and I updated the visualizer to show just our full state machine. So that so moms down jumpers to dragging and then we can mouse move and then it's, oh, then it has. The side effects? And then it's back to dragging again, go mouse up and then we jump to idle.
56:00 You can find them at Brilliant. Org, Brilliant yeah
That's really, really sleek. I all right, that's, that's amazing. We're going. I'm gonna take this code and paste it in a gist which you can find. If I like, I'm actually going to do it now, so let people get it right. That's that, is it, that is, that is, that is XState, we like, where do people find you? David? How do people find you? and how do people find XState? Yeah, so my username on Twitter, GitHub, anywhere is @DavidKPiano, and so that's where you could find me. Also on Copan, where I have a few X8 examples as well XD. You could find more information on ext.js. Org. BAM yeah, before we go, I would just like to give a little bit of another shot at two. Brilliant, a wonderful sponsor. You can find them at Brilliant. Org, Brilliant yeah. Org, slash FFF. That link is good because it gives you 20% off. It's really nice. For learning computer science fundamentals and machine learning math, they have this interactive challenges instead of the normal video courses.
That you. That might not be absolutely perfect. When you're learning these kinds of concepts, we really, really like them. Make sure you check them out. And if you're doing these things, and yeah, thank you for supporting your show. With that said, we're going to wrap the stream off because we are we're a little bit over time. I would like to thank everybody that joined us. It's always such a, such a pleasure to start the weeks off with a stream particular. Fitting like in a state today. Bendy. But it's still, like, with David's help, managed to actually do a proper drag-and-drop. Implementational XState, which is super, super nice. I've been meaning to check out X Tech for a long time because so many people are excited about it. And I really see now, especially with the III, like, thinking about the structure and application in this way. Mm-hmm, it's, it's just really, really nice, and it also makes it big.
Least its communicate with stakeholders. There's so many nice things about this. Yeah, I, that's it, I'm going through. Close the stream off, thank you so. Much everyone for joining and until next Monday morning, stay curious.
Related talks
-
Goodbye Slop; Welcome Determinism (Beyond the Prompt)
Beyond the Prompt 2026 (AG Grid & Bryntum, London). 30:27, 29.2K views -
Let’s Learn State Machines
Learn With Jason (CodeTV), 2019. 1:05:29, 19.7K views -
Model-based testing with state machines
Web Zurich meetup, 2020. 18:12 -
Visually Create State Machines
Learn With Jason (CodeTV), 2022. 1:19:20, 3.4K views