Check out a free preview of the full State Modeling in React with XState course
The "Parameterizing Actions" Lesson is part of the full, State Modeling in React with XState course featured in this preview video. Here's what you'd learn in this lesson:
David demonstrates how actions can be parameterized for more reusability. Custom parameters are passed to the useMachine hook which overrides the default parameters in the machine.
Transcript from the "Parameterizing Actions" Lesson
[00:00:00]
>> All right, so let's get on to parameterization. This is a feature of XState that makes it, it's just basically a refactoring feature. But it also makes it easier to visualize how different parts of your machine are working and just showing what they're supposed to be doing. If we go back to the scratch.index file.
[00:00:23]
Index.js file, we could take this and we could parameterize it. Basically we're just refactoring it. So, over here, we want to increment the count. So we could do something like, call this const increment count. And, put that over there, and then have this just be increment counts. This is just standard JavaScript refactoring.
[00:00:51]
So this is going to work the exact same way. If we go home, we see that it's still increments exactly the same. But what we could also do is, we could take this, make this a string, and as the second arguments to our machine, we could say for example, actions Increment count, we could have that be that same action, that same implementation.
[00:01:20]
In this case, it's the same as increments counts. And everything's going to work the same. So you might be asking yourself, why exactly do I want to do that?
>> Why do I want to do that small amounts of refactoring, if it's going to do the same thing?
[00:01:38]
And the reason is because with XState react, and XState in general, you have the flexibility to change what side effects do. Sort of like you would mock in unit tests you could change the behavior of what the side effects are doing in a given implementation. So for example, let's say that we want to increments by 100 instead.
[00:02:03]
So in use machine in the second arguments, we could specify increments counts to be something different. So we could say assign and we could add 100, instead of one. And so now this is going to be specific to the machine being used over here. So, if we go here and reload and click here, now we're going to see that our increment counts does something different in this component.
[00:02:34]
And so this is really essential to having these machines. That are reusable that you could use in different components and that do different things depending on which component they're in or which behavior you want. And you could also do things like just have this be I don't know, an empty function that doesn't do anything and you could leave the implementation details up to the consumer of this machine.
[00:03:04]
So if I forget to add that, XState react is going to warn you that that action wasn't implemented. I probably have warnings hidden. So, you won't see that over here. But if I click over here. But yeah, you will get a warning if you have warnings showing over here that that action wasn't implemented.
[00:03:28]
And so it's up to you to just go ahead and implement that. So we could just change this to increment count. Are there any questions on that?. So, the question was, what can be the thing that's passed into actions? Can it be an external module or something like that?
[00:03:47]
Yes, essentially it could be anything. So, an action is something that, if it's not a built-in XState action, it could be a function that takes the current context and event, and basically does whatever you want here. So if I alert increments, then I click here it's going to say increments.
[00:04:10]
Now that function can be anything. It could come from a module, it could definitely be an external module, it could call a third party library. And that's why actions are really, really useful. And parameterizing actions are useful too. Let's say that you want to do logging or telemetry or something.
[00:04:31]
Is our actions a good place to do that? It depends, but mostly yes. So, let's say that we do have, let's just have a telemetry over here. And right now it does nothing. But we want to add telemetry over here. And we could console.log, let's say, logging telemetry.
[00:04:55]
And maybe pass it the events as well. And so we could define in specific states where we want that telemetry to be. So let's say we want telemetry here. And we also want telemetry, whenever we enter pending, we could have it entry telemetry. And so now we're going to see that we do get that telemetry over here.
[00:05:21]
And obviously it's just logging to the console. You can make it do whatever you want. But sometimes, let's say that you want to have it happen on every state. So, there's a couple of ways to do that in react, you could just use effect. And so whenever the state changes, that's when you want to, you could console.log the state, and just do all of that.
[00:05:50]
Now, when you're using XState in the context other than react, you have what's called a service, and in XState react that's returned as the third part of your tuple over here. A service is a machine that's running. It's that interpreted service or sorry, the interpreted machine. And so you could do service.subscribe.
[00:06:17]
And you could do whatever you want over here so you could log telemetry. In this subscribe function you do get the state, and remember the state includes everything, the context, the event, any actions, and if you want to clean up this effect, so you have const subscription, you could return sub.unsubscribe.
[00:06:42]
And so that's how you could do that cleanup over there. In general use effect is useful when you want to do something every single time the state changes. But otherwise if you want to be more granular, then yes, use actions instead.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops