State Modeling in React with XState Refactoring to XState useMachine
Transcript from the "Refactoring to XState useMachine" Lesson
[00:00:33] And so hopefully, you're familiar with XState. But if you're not, XState is basically a state machine state chat library, that allows you to define these state machines in this object, the same one that we've created before. Put it in create machine and then you have a machine that you could either use directly via the machine transition function, or you could interpret it and have it be a live running instance that keeps its own states.
[00:01:04] So, we're gonna be using XState now, and also we're going to be using XState react. So if you go to the packages and the documentation, and click XState react, this is the package we're going to be using. And if you're familiar with useReducer, which hopefully after the first exercise, you are, then XState react is going to feel very familiar to you.
[00:01:28] So, let's go home. And what I want to do is, I want to just do the tiniest amount of refactoring to make this work with XStates, instead of use reducer. So here's what we're going to do. This can be converted to a machine in XState, by passing that object into create machine.
[00:01:55] And so this is exactly what XStates expects. We have initial States and all of these events in the on object. This machine, of course has a transition function. Let's actually console.log this. So, console.log. We call this alarmmachine.transition. Alright, so alarmmachine.transition. This is going to take two arguments. The first argument is going to be the current state.
[00:02:33] So let's say that we're in the pending state and the events. You could represent in events as a string or as an object. Just for now, I'm going to represent it as an object. So when we do that, you're going to see that this will be Break, but I want to just show you what the console.og of this machine is.
[00:03:00] All right. I guess it won't break it. Just won't show the right thing. All right. So we get a state object. And this state object includes a lot of things, including the events that we that we sent over. But it also includes the value. This value is going to be that finite state representation.
[00:03:19] So, this is going to probably be the most important property of the states, that you should be concerned with. And also the context. We'll talk about context a little bit later, but that's for holding any infinite or extended data that you also want to represent in your state.
[00:03:38] So taking a look at value, that's exactly what we want. So if we go back to our alarm reducer, we could say that our next state is going to be, the alarmmachine.transition. The state and the events and then we could return next dates. The initial state is actually that state object.
[00:04:02] So it's no longer just this state value, but it's going to be the alarmmachine.initial states. And so that's a property that gives you that initial state object. So we could say the status is going to be that state.value. Which again, this is the finite state. So it could be pending, or it could be active, or it could be inactive etc.
[00:04:34] Everything basically stays the same over here. And so as you notice, we're not using XState react yet, instead, we're using XState, to take that machine and just simplify things for us a bit. So, let's test this out. When we click, should go after two seconds to success and it goes back.
[00:04:54] So our logic still works exactly the same. I would barely call this boilerplate. It's not really too much boilerplate, but if you want to use XState in this pure way, you're absolutely welcome to with XState reacts though. We have a hook called useMachine. And useMachine makes things a lot simpler with working with machines.
[00:05:17] So instead of use reducer, we could use machine. And we're gonna replace the reducer with the actual machine, which is this alarm machine. So alarm machine. And so, you get basically the same tuple over here. You have the states and you have dispatch. In reacts, this is actually called send.
[00:05:44] So, that should be a nice differentiator between Use reducer and use machine. So when you see send, it's likely a next state thing. If you see this batch it's either redox or use reducer. Plus send is actually a lot easier to type. So I like using send. All right.
[00:06:01] So now let's test if this logic still works. We have usedMachine, alarm machine, state and sense. So everything else should be pretty much the same. And we could also get rid of this alarm reducer over here, since we no longer need it. And moment of truth. There we go.
[00:06:24] Okay. So our alarm logic still works exactly the same way. And so hopefully, you could see that usemachine. Feels exactly like use reducer and you could use it in the same way. There are some nice conveniences too. For example, if you are sending in events object and it only has a type, you could send just the type as well.
[00:06:50] Normally it's best practice to send the full object if you do want to add some sort of payload later, but this is perfectly fine. In fact, we're doing that here as well. That's still going to work exactly the same. So we click here, goes there. Yeah. This use effect has a missing dependency.
[00:07:21] The ES Lynch rule, will Tell you that it's missing send. Send is stable, but if you do want to be safe, you could also add it there too. But normally you don't need to do that. And as we're going to learn in future exercises, use effects are actually handled in XState itself.
[00:07:46] And so we're going to see how that works.