David Khourshid
David Khourshid (known on Twitter as David K. Piano) is a software engineer for Microsoft, a tech author, and speaker. Also a fervent open-source contributor, he is passionate about statecharts and software modeling, reactive animations, innovative user interfaces, and cutting-edge front-end technologies. When not behind a computer keyboard, he’s behind a piano keyboard or traveling.
Using useEffect Effectively
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
Transcript
Intro
All right. Hello everyone. My name is David Khourshid, and my slides will be showing up shortly, I'm sure. Oh yeah, there it is, okay. David Khourshid, I'm at davidkpiano pretty much everywhere. I'm very excited to be in London again. I work at Stately.ai, where we think a lot about state, logic and effects. But enough about me if I keep going, then this talk is going to last longer than your next Prime Minister, so let's get on with it.
[00:41] Okay, so of course I work at Stately and one of our engineers, Matisse, you might have seen him, he's in your NPM, your node modules, I guarantee it. He's one of the most talented developers I know. Yesterday he created a PR where he asked, "Am I 100% confident in this fix?" Hell no, it's based on useEffect. So we're going to be talking about that today, our favorite hook, useEffect.
But let's start from the beginning. Who remembers class components? So yeah, some people really want them back, so do I. All right, so in this example, I remember that when React came out, I was very excited for it. I'm like, "Wow, this is going to change everything." And React did change everything on every single render. So over here we're doing what most components do or what most reactive developers do, which is fetch data and show it on the screen. I admit that's 90% of your job, but we had a nice convenient little lifecycle hook componentDidMount to do that in. But now things are different, we have useEffect. So I remember I learned about useEffect in 2018 and I was very excited to use it, because I'm like, "Wow, this makes things a lot simpler." So instead of making these big bulky classes, we have these hooks that we could put things in.
[01:58] I wanted to fetch data. It was 2018, so I wanted to use new JS syntax and it was an effect, so I put it in UseEffect, tried this, React yelled at me. It said, "Listen, this async/await stuff, it's fancy, but you cannot use it like that. You have to..." It does infer that, "Hey, I don't know what to do with this promise that you returned from useEffect." So we had to do things like it was 2015 and use .then. So I fetched some data, then I set the data, I'm like, "This is simple. I just put it in the useEffect. I get my data, I'm good to go, right?" Wrong. Guess what happened to my AWS field the next day? Yeah. So this by the way, it will keep fetching and fetching and fetching and React won't tell you that, "Hey, this is going to occur as an infinite loop."
All right. So at this point I'm like, "Okay, maybe I should read the documentation a little bit." So I scrolled all the way down. And so there was a tip, it's just a tip. This very crucial bit of information is a tip in the current React docs, optimizing performance by skipping effects. And so I learned that you're supposed to use this little dependency array, and since this didn't really have any dependencies, you just put it empty like that. If you look at it sideways, it looks like an agonized React developer screaming into the void, yeah. All right, so I learned my lesson, I learned what the dependency array is for, and so everything was good, right? Well, now I discovered that we have something called a race condition, because when I fetch something with an ID and then I decide, you know what? I want to fetch something with a different ID. If that ID is cast, then that promise is going to be resolved first, while the first one is still going, because we didn't cancel it.
[03:58] So now we have to do the dance. This is a dance that so many of you have done before and that's having this is canceled false flag or React calls it, ignored in the official documentation. And then you have to make sure that we haven't canceled this promise. You have to have a cleanup in there and you have to do all this. So some of you just copy and paste this. Some of you put this in a usePromise or a useAsync custom hook, which is totally fine. And this worked well for a while until React 18, where effects execute twice on mounts. So when I first discovered this, I didn't know it was a React 18 thing. I'm like, "Am I doing something wrong in my code? What did I do? Did someone change something? Was it the Tories? I have no idea."
useEffect
&
React 18
[04:48] So what's actually happening over here? So I looked it up and saw, okay, we mount an effect and then React, it's actually simulating an unmount and then React is remounting it again. But I was wondering why the heck was it doing that? And so I did a lot of digging around. I was looking at the second official React docs, which is random Twitter threads by the core maintainers, and I realized that useEffect, it felt like a defective thing. I'm like, "We really, really shouldn't be using it. And the more we use it, the more we feel like this, right?" But of course I calmed down a bit, researched a bit more, learned about how useEffect works. And so the answer might surprise you. It doesn't…for many effects, it actually does work. But there's many telltale signs where you could see, "Okay, maybe I shouldn't be using useEffect."
First of all, React 18’s double exec, that thing that it does only in strict mode and only in development environments, this is an eviction notice, basically. When this happens and part of your app breaks, it's basically React telling you, you shouldn't be using this effect inside of useEffect. Also, there's other symptoms, like long dependency arrays. When you have complex conditionals inside of your effects, if you're missing cleanup functions or if those cleanup functions themselves are conditional or you might have adhocs that state calls just littered throughout the place, these are all pretty telltale signs or side effects that might indicate you're probably using useEffect wrong.
What are Effects and how are they different from events?
[06:33] Okay, which effects then should we be using in useEffects in the new Reacts beta documentation? Which I'll give a link to later. They say that there's really two types of effects. There's the Effects with a capital E, those Effects let you specify side effects that are caused by rendering rather than by a particular event. So we're going to get into the difference, well right now.
So React refers to two types of effects, Effects with the capital E and events. So effects that are supposed to happen in eventHandlers, but I think this is a little confusing. So for the duration of this talk, I'm going to be calling them activity effects and action effects.
[07:19] And so activity effects are something that is an ongoing process. It's something you don't forget about while you're in the life cycle of your component, you're intently watching it. So this might be a subscription or watching a live stream of a head of lettuce or something like that. An action effect is something where you just explicitly execute it, it's fire and forget. You don't care what the end result of that is, like Brexit.
So what is useEffect for? useEffect, the hook specifically is for synchronization with activity effects, not with action effects, but with activity effects. So one example of this is for example, a listener, a resize, a mouse move, something like that, where you create a handler, you add that handler and you make sure to use that cleanup function to say, "I don't want to listen for this anymore." And because activities are ongoing things, it's like watching television, where it doesn't matter how often you turn on and off the TV, the channel is still going to keep going. You're not imposing any side effects by turning it on and off. It's not like you turn off the TV and the BBC is like, "All right, let's cut it, this person has stopped watching."It doesn't work that way.
Where do action effects go?
[08:39] So where do action effects go then? We know that we can't really have side effects and render in, you actually can, but we won't get into that here. We know that putting it in useEffect is awkward, because David said so. But what about outside the component? That's an idea. So where do action effects go? In reality, they go in eventHandlers or sort of. In this example we have an onSubmit and we are submitting the data directly inside that onSubmit. And I'm going to show you the alternative later, but the real mental model is you want to put your fire and forget, your action effects as close as possible to the event that would've caused the effect. And so here's how this helps with React 18, we know that when something changes, our component is going to re-render. And if we tie that effect to rendering, then React, remember it has the ability to just keep re-rendering that component. And because you tied it to rendering, it's going to just keep executing those effects, which we don't really want.
But move the effect closer to the eventHandler, and you avoid that problem completely, because you're not tying it to render, you're tying it to the actual event that cause that effects to happen. So action effects happen outside of rendering.
[10:01] All right, so here's an example which actually goes through quite a few issues and I've seen this before, I've even done this. There's an isFocus prop. And so this isFocus prop makes sure that when we focus the components, so isFocus equals true, we're listening for that state change. And so when that state changes, we are going to execute that useEffect, which is then going to focus the event. So there's a lot of indirection going on here, just in order to get that component to focus. And also there's a possibility of an impossible state. What if you have multiple isFocus is true? In short, isFocus shouldn't really be a prop. But let's see how we could refactor this at least outside of useEffect.
So instead we could use a forward ref and we could just consume that in the components, where we have this inputRef equals useRef. And even though this is a fancy input, we could use forwardRef to grab that. Or if you really want to, use imperative handle. I didn't put it in the slides because I want people screenshotting it and being like, "This guy's recommending use imperative handle, that's too spicy for this talk." But anyway, check it out. We are doing the side effect directly inside of the eventHandler. And so the result is we have a very clean component, we have no useEffects in sight and this is just extremely, extremely simple.
[11:33] So when we think about this though, like executing an effect directly inside the eventHandler, it feels imperative. It feels like when something happens, execute this effect feels a little weird, feels a little side effecty and not really functional, right? But check out the declarative approach where we're saying when something happens causes the state to change and depending on which parts change, this effect should be executed, but only if some condition is true. And React may execute it again for some future reason, but only in strict mode, which you shouldn't disable for some future reason. And I try to hear the explanation for this, I think it's something with offscreen mode or every single time I hear it I lose the reason why, but just don't do it.
Beta React docs
[12:37] Okay, so now we're going to get into the beta React docs. Just checking the time, not much time. Okay, so beta React docs. I'm so thankful that these docs exist by the way. So by the way, if you go to reactjs.org, there's a nice header over here and you could go directly to the beta React docs. Wish we had this three years ago, but it's great that we have it now.
And there's a section in here called You Might Not Need an Effect. So we're going to go over a few of the sections, not all of them, because then this would be a much longer talk. But yeah, let's go through them one by one, especially the ones that are most common to what I see people using useEffect for where they shouldn't.
[13:17] So the first one, you don't need useEffect for transforming data. So here's an example over here where we're calculating the total of a number of items right in useEffect, which makes sense. Whenever the items change, we need to set the total. Guess what? That's a very imperative way of thinking. Instead, what we could do is just put it inside a useMemo, because the total is a derived value and useMemo is very good for derived values. But guess what? You might not even need useMemo. Honestly start without it, and only if you start to notice performance problems should you start to useMemo, I'm saying use a lot. But yeah, much simpler, get rid of the useEffect.
And of course, we know that putting a set state in the useEffect, it could cause a whole bunch of problems anyway, leading people to think, "I will never understand why the default behavior of useEffect is an infinite loop." I've run into this before and the React docs warn you, "You shouldn't do this, this is why." It's because this is going to trigger a re-render, which is going to trigger the effect again, et cetera, et cetera.
You don’t need useEffect for communicating with parents
[14:24] Okay, you don't need useEffect for communicating with parents. This is an interesting one that really highlights the indirection that's going on. So we have onOpen and onClose props. And so whenever we open something here, let's say that this is a product view, we change the state and then depending on whether it's open or closed, we're going to call those props. And we're doing that by putting isOpen in a dependency, which is going to trigger the useEffects.
So you could see here we're clicking states changing then we have an effect, lots of indirection. So instead get rid of the useEffects, put it directly in the eventHandler and now it becomes much more straightforward and easier to understand. So now instead we are just calculating the next state, because we know the next state of that is open and depending on that state directly call on open and on close, and then you could even put it inside of a hook. Sorry.
You don’t need useEffect for subscribing to external stores
[15:28] All right. You don't need useEffect for subscribing to external stores. This one is a really interesting one, because it goes counter to what I was just talking about. It's like useEffect is really good for subscriptions, right? Well, over here I'm subscribing to a store API and all I'm doing is getting some specific value whether I'm connected or not to the store API. And then I have an unsubscribe here. There's still a little bit of indirection here, because we are setting a local state variable.
Guess what? You could actually get rid of this and use the useSync external store hook, which has three parts, a subscribe part where you tell it, "Here's how to subscribe, here's a function you need to call a subscribe." The get snapshot part, which is, "This is the value that I want to get and here's how to read it from that store." And a server snapshot where it's just good for SSR. So you put all those three things together, it's going to automatically subscribe and get you the value you need. No use state, no useEffect. It's a really brilliant hook. So I do recommend that you at least try it out. They say it's only for library authors, but they also said like, "Do not use or you will be fired. It's only for React maintainers." But we're seeing libraries use it for whatever reason, like preact signal and stuff like that. So go ahead and use it. Not that one, but useSync external store.
You don’t need useEffect for fetching data
[16:51] All right, this one is a big one. You don't need useEffect for fetching data. Like we talked about at the beginning, that was one of the big reasons that we used useEffect. So instead of all of this that we were doing before, just use the framework. Whatever you're using, you're likely using a framework. Remix has a really nice loader over here, next.js has getServerSideProps. And so this is going to be available to you directly in the component. And then there's a library that hopefully most of you are using for fetching data, which is React Query. But notice over here I'm doing something different. I'm doing queryClient.prefetchQuery, because the idea is that we want to start fetching as soon as possible, which is the subject of a whole other talk. But so yeah, instead of useEffect, really useQuery, next.js has useSWR or just use, right?
This is going to happen in the future if you're not familiar with the use hook, it basically acts the same. Or this is going to be the new upcoming way of doing suspense, I think. It's an RFC, React might kill it. They like doing the whole Google thing where they kill stuff. Just kidding, they've shipped a lot of really great stuff.
[18:09] But the important thing is this cache over here. This cache means that whenever we try to read this, we are not going to keep re-fetching and re-fetching. I guarantee you, you're going to see React tutorials where they forget about this whole cache part or they start fetching in here, you're going to get waterfalls again. So just make sure fetch as early as possible and cache.
And Dan talks about a lot of problems with fetching and useEffect. First of all, the race conditions that we talked about, there's no instant back button. You're going to see loading spinners everywhere when you try to go back, because components are going to try to load again. No initial HTML content, so you're going to have even more loading spinners and you're chasing waterfalls, because the parent's going to unload, and then when that's unloading, the child's going to load when that's unloading, et cetera, et cetera. And so you want to avoid those things.
You don’t need useEffect for initializing global singletons
[19:00] Okay, so another thing, you don't need useEffect for initializing global singleton. So here's what I mean. Let's say that we've done this a lot, where we execute some sort of effect when our app starts. And so we're like useEffect is the right place for effects, right?
So we're calling the store API.authenticate, but we know that in React 18 this is going to run twice. So instead we use a ref and we say, "Hey, did this already run?" Maybe not, but this is honestly a red flag, so I recommend you not do it. So instead of using a ref, we could just stick that outside. But guess what? Why don't we just stick the entire thing outside? Look how simple that is. A lot of you might be internally screaming. This is something that Dan recommended on Twitter, so I feel okay putting this on the screen. But if you're using next, you could check if type of … was undefined or not and call it conditionally like that. And then if you're going to scream about testing, then just wrap it in a function and then you could even inject that store API, do whatever you want to do, just do it outside of the component.
You don’t need useEffect for handling user events
[20:10] And then the biggest one for me, you don't need useEffects for handling user events. And so this goes to activity effects versus action effects. So now we're talking about action effects.
So in this one we are submitting a form and we're setting all of these variables. So setIsLoading is true, set the form data to the event. And so that's going to be indirect and trigger a change. This is wrong. What you should do is move it inside of the eventHandler. So move it inside of submit and then you might need to add a whole bunch of extra logic, but because you're not using useEffect and you're isolating it to that eventHandler, you could easily abstract that to a hook. My favorite type of hook looks like this, where you have a state and a send and all you have to do in your components is send events. This is useReducer, this is XStates, the library I maintain, this is Redux, Zustand this works the same way.
[21:09] So here is a bigger example. I wanted to just make this cool video, where it's a thumbnail, but when you click it, it goes full screen. And then there's many ways to close it. You could click outside of it, you could press the escape key or you could wait for the video to be over. There's three useEffects that are handling this. So the first one we are checking isPlaying. And so if we are playing the video ref is we have to play it or we have to pause it, if it's not. The second one, we are listening for the video to end. And if it's not ending, then we have to set isPlaying to false. And remember, this is going to trigger some indirection, it's going to trigger the state's change, and then the state is going to trigger the previous effect. And same thing over here, when we press the escape key, again, we're setting Is playing to false. And now we have a little bit of cleanup too.
So the way I like to think about these instead, in terms of declarative effects is by using a state machine. And no, I'm not going to talk about exceeding this talk, but you could talk to me afterwards about it. So with state machines, you declare the effects that are going to execute directly on the transition. And I think this is brilliantly simple. So for example, when we're in mini and we transition to full, we're doing it on a toggle and we play the video. Same thing when we're going from full to mini, we go from toggle and we're pausing the video and then we do the transition. So if you haven't used XState, just imagine this as Redux or your standard reducer. Imagine if you could execute effects directly inside of your reducer. It's basically the same idea.
[22:46] And so I really like this, because it really gives you a visual way and a declarative way of thinking about all of your effects without having to just tangle your mind and think, "Okay, when is this effect going to execute? I have absolutely no idea." So yeah, this is just my way of telling you, start looking into I guess state machines, because state machines are purpose built for declaratively expressing all of these types of effects.
Summary
[23:16] So in summary, or not summary, but where do action effects go? Not really eventHandlers, but technically they do go in state transitions which happen to be executed at around the same time as eventHandlers. Now I don't have much time, so let's wrap up with a summary.
UseEffect is for synchronization.
Activity effects go in useEffect.
Action effects go in eventHandlers.
You should render as you fetch.
And last but not least, state transitions trigger effects. So with that said, I want to thank you all very much.
Questions
[23:55] Eli Schutze: Amazing. Please, step into my office. Thank you so much, David. That was fascinating and also very funny, which I appreciate. Remember you can ask questions on the sli.do, S-L-I.D-O. The code is 2124. As per usual, the people want to know what presentations software are you using. Because it's beautiful.
[23:16] David Khourshid: So this is slides.com, because I'm too easy to learn. Keynote. And also slides.com is super easy, plus you could customize it with CSS. They have that magic move thing too. It's really Nice.
[23:16] Eli Schutze: And you can present offline. That's what I use [inaudible 00:24:36]. Yeah.
David Khourshid: Oh yes, yep.
Eli Schutze: Let's talk about effects. I love you might not need concept, because I'm a simple gal. I don't like to over-complicate things. But if I wanted to take all of this into say, the real world, a team, a job, are there any tools we could use, some linting, some notes, a blog post, any resource in order to ensure we're conscious of these things?
[23:16] David Khourshid: Good question. I mean, I guess you could watch my talks, but then they're going to be like, "Oh, this is just David blabbing on about useEffects." So I'll write a blog post about it. The official Reacts docs, the beta docs honestly, stop reading the old docs, read the beta docs, those are going to be the resource for basically everything I talked about during this talk. And they even have a couple more examples of where you should not use a useEffect. So definitely read through that. As far as linting rules, just let React 18 make your app crash in developments and be like, "Oh, why did that happen?" Probably a useEffect.
[23:16] Eli Schutze: I feel like I know the answer to this, but what are your thoughts on that lint rule, that's don't put functions in your eventHandlers?
[23:16] David Khourshid: How about don't add lint rules until they actually become a problem, how's that?
[23:16] Eli Schutze: That's great. Cheers for that. All right, we have a few questions. All right, fetch as your render sounds good until you depend on arguments for your request. What is the best approach then?
[23:16] David Khourshid: Well, think about when those arguments happen. The user probably initially yates it or it's coming from an outside source. So for example, the user might press a button, might fill out a form, and then when they submit a form that point where they submit a form, that's when you should be initiating the request. What a lot of React developers do is they'll submit a form that sets a state or that gets passed down as a prop to a component. And then the component's like, "Oh hey, I have a prop. Now I can read that prop in fetch data based on that prop." But there is a lot of in interaction there. So start fetching as early as possible. You're going to learn that React rendering is not an event or it's actually not the events that you should be caring about. The user actually doing stuff or some external thing doing stuff, that's what you have to focus on.
[23:16] Eli Schutze: There's a lot of questions and I'm going to bundle them together about all the alternatives. So isn't useReduce good for fetching? Or do you think we're going to use Redux again? Or when would you use useEffect without a dependency array? What about use event? All the uses.
David Khourshid: So use events, dead. React likes killing stuff.
Eli Schutze: The Liz Truss effect.
David Khourshid: Yeah. What were the other alternatives?
Eli Schutze: Reducer.
[23:16] David Khourshid: Things like, all right, useReducer, redux, et cetera, these are state containers. They're not really ways that you would fetch effects. But like I mentioned with state machines, you should be thinking about when your state changes, you should have some way of indicating this is a new state and these are the effects that are supposed to happen. A lot of times when we think about it, we're like, "here's a new state. And then we have some middleware that runs where it's like, "Okay, maybe I'll fetch." But I think that both of those should go together.
[23:16] Eli Schutze: Thank you, David. What tool did you use to visualize the state machine in your slide?
[23:16] David Khourshid: Great question. Not a planted question, I promise. It is a Stately.AI/editor. It's free to use, play around with it.
Eli Schutze: It's really pretty.
David Khourshid: Yeah.
[23:16] Eli Schutze: Okay. One more. Oh, actually maybe two more. Did you ever think about contributing to the React docs?
[23:16] David Khourshid: Yes. So I did contribute to the React docs once, because they had use timeout MS. It was for some very, very old suspense API, but I was like, "Wait a minute, it just says use timeouts in the docs. I could add that little MS to the side." And that was my first React contribution, because their actual source code might as well be closed source. There's bit shifting in all these weird fiber stuff and I'm like, "That is very unapproachable for any dev who does not work at Meta and probably most devs who work at Meta." So yeah.
[23:16] Eli Schutze: I think that's fair. And then finally, great talk, are your slides now or later going to be posted online somewhere that we can [inaudible 00:28:58].
David Khourshid: Yeah, of course.
Eli Schutze: Cool. Follow David on Twitter at davidkpiano.
David Khourshid: davidkpiano.
Eli Schutze: Thank you, David.
David Khourshid: Thank you.
Eli Schutze: Round of applause, please for David.
The State of XState
React Finland 2021React Finland 2021
18 min
The State of XState
Over the past few years, state machines, statecharts, and the actor model have proven to be viable concepts for building complex application logic in a clear, visual way with XState. In this talk, we'll take a peek into the future of XState, including new features in the next version, and new tools and services that will make it even easier to create and collaborate on state machines.


The Visual Future of State Management
JSNation Live 2021JSNation Live 2021
32 min
The Visual Future of State Management
Learn about state modeling with state machines and statecharts can improve the way you develop application logic, and get a sneak peek of never-before-seen upcoming visual tools that will take state management to the next level.


XState: the Visual Future of State Management
React Summit Remote Edition 2021React Summit Remote Edition 2021
35 min
XState: the Visual Future of State Management
Learn about state modeling with state machines and statecharts can improve the way you develop your React applications, and get a sneak peek of never-before-seen upcoming visual tools that will take state management to the next level.
Transcript
Intro
Hey everyone. My name is David Khourshid. I go DavidKPiano online on Twitter, GitHub, whatever. And I want to talk to you today about the visual future of state management and how X State is going to bring that future vision to reality.
Visuals
[00:35] Talking about visuals, you probably know where the Ben diagram is. It's a visual and an exact way of representing commonalities between two or more different things. And you might have also used a sequence diagram before to describe how different parts of a system communicate with each other. There's also state machines and state charts, of course, which I've been talking about for a while and state machines and state charts fall under this visually exact diagram category, because diagrams like these are really useful in conveying relationships in a visually unambiguous way. And they each have their own special notations for denoting specific things.
And with state charts, we have the same type of thing. We have arrows and boxes just describing how dates and logic can flow over time. David Harel, who is the inventor of state charts, calls this a visual formalism. And he describes that visual formalisms are diagrammatic and intuitive, mathematically rigorous languages, thus, despite their clear visual appearance, they can complete with a syntax that determines what's allowed and the semantics that determine what the allowed things can be. And I recommend reading his paper on visual formalisms for more information on this really, really interesting idea of basically these diagrams that are mathematically rigorous and also executable.
[02:16] The way that we typically code application logic, whether it's in React or anything else doesn't really lend itself to a visual formalism or to anything really. We tend to collocate data and logic close to the source where it's used such as in event handlers, or sometimes in custom 
React Hooks if we want a little bit more organization. While this may be convenience to code, the problem one is that the logic is hard to understand, especially as it changes over time due to events or anything that can happen within the app. And the problem is you can't discern what can happen or how an application can respond to any event or signal at any point in time. And that connection logic resides in the head of the developer who added the logic, which isn't really useful. And you end up with things such as ad hoc logic as well, which obviously should be dried up. But the problem is that when you add that ad hoc logic, the logic, when you dry it up, you might put it in a function or something, and that function may end up itself being ad hoc logic, just living somewhere else. So you're still not centralized seeing everything which definitely becomes a bit of a problem.
Reducer
[03:44] And enter the reducer, popularized Flux and state management libraries like Redux, reducers provide a way to contain this logic in a centralized convenient location. One hugely important beneficial constraint of reducers is that it forces you to interact with the logic sending events or actions as they're called React and Redux side.
By the way, the naming of actions was a mistake, at least in my opinion. So we're going to be using the term events in presentation, but here's why dispatching events is actually a really good thing. It forces you to reify what can happen at your app in any given point in time. The user may click a button, a fetch may resolve or reject, a timer might go off. All of those are events. And thinking about your app in terms of state and events really simplifies the mental model, at least in my opinion.
[04:46] However, this isn't easily visualized either. Reducers typically contain switch statements, or if statements to discern what should happen when an event is received, thus distinguishing how the behavior of your app can change, becomes a lot more difficult. It mixes those switch statements and those if statements, and so you have to piece together the logic navigating through a bunch of these statements and defensive logic just to discern what the behavior of your app can be at any given point in time, it's all in a single function. And it's hard to pull that apart.
State Machines
[05:25] State machines are like reducers and they can even be written as reducers, but instead of mixing all the logic together, it cleanly separates behaviors into what are known as finite states. A finite state represents a behavior, which is what the current state is of some actor and how it could respond to events. It might respond to an event performing an action or changing its behavior or anything like that. And that's represented these transition arrows that go from state to states or an event might not be handled in which case the default behavior is to ignore that event. In reducers, this often requires a lot of defensive code, but with state machines it's spilled right into the mathematical model. And more practically this separation prevents impossible states, which guarantee that two behaviors can't occur at the same time and impossible transitions since all transitions need to be explicit and you can't have any implicit transitions.
State Charts
[06:35] State charts take this idea of a visual formalism, one step further introducing hierarchy. Although state machines provide a way to cleanly organized logic, they suffer from combinatorial explosion of states and transitions, especially when different finite states are actually related. By extending the notion of state machines to be a hierarchical graph, or a high graph as David Harel calls it, we can group states together and represent common transitions cleanly. We can also isolate logic so that we can see the bigger picture instead of having to understand all of the little implementation details in one big flat structure.
Like state machine state charts are also mathematically rigorous, but they can express a lot more complex logic than a state machine can. And it solves the problem of combinatorial explosion within state machines, because it allows you to group related behaviors together. That's a state chart.
X State
[07:39] And this is why I created X State a few years ago. I wanted developers to be able to represent state machines and state chart in a way that can be coded cleanly and can also be automatically visualized, which is why it has this js on like objects notation. Unlike your typical reducer, X State is state first, non events first. It forces you to focus on separating your behavior in terms of finite states, and then specifying the transitions based on events. Now you can do this without X State or any library for that matter, but you would involve things like nested switch statements, and it wouldn't really be easily visualizable. Like I mentioned earlier, a machine can be represented as a reducer. And that's what this machine.transition function is. You provided the current states and the events that just happened and you get the next state.
But what it could also do is provide some event emitter interface in which it contains the state itself and you could send it events and have it manage its own states. And this is really useful in situations where you don't want to have to wire up together where to store the states. And in addition to that, it's also observable. You could use this with RxJS as well, and it doesn't need to be said, but this is completely framework agnostic. You could use it with any framework and it is set up so that it's easily integrated. Whatever the word is. You could use it with any framework, like Reacts, Vue, Angular, Svelte and more.
[09:25] But speaking of React, there's a lot of useful utilities that allow you to more easily use X State machines with React. And one of these is the useMachine hook, and this is just like the useReducer hook.
In fact, if you know useReducer, then you basically already know useMachine. Instead of passing a reducer, you would pass a machine that you created and you get the same two expected values from the twofold, the state, which represents the current state of the machine, and send, which represents a way for you to send events to that running machine.
[10:06] Now, the state also has a few utilities such as matches so that instead of having to figure out what the exact finite state of the machine is, you could just pass in the expected states or part of the state, like first, second review in this wizard form example. And it provides a nice clean way to show different parts of the component. And of course you could also send events, whether it's just the events string or an entire event object. It's really useful and really handy, just use it like you would useReducer.
Recent and upcoming features of X State
[10:46] But I do want to talk about some recent and upcoming features to X State, and X Sate React that I am particularly excited about.
The first one is useInterpret. useInterpret, the goal of this is to interpret a machine, create a service, and it just returns that service. And then that service is a single object, which is a reference to the interpreted version of that machine, which never changes. This makes it really useful in Context. If you were to create Context with React, now you could pass that service into that Context provider and use it wherever you want, such as a wizard. Now, the great thing about this is that since the service doesn't change, it's not going to cause a lot of re-renders. In fact, it only updates once, which is when the service is created. You're guaranteed to never have any extraneous renders. And the way that you would use this is a combination of two hooks useService and useContext.
[11:59] You grab the service from the Context, which is that ServiceContext, and then using the useService hook, you could use it just like a machine. Instead of passing a machine in, you pass the service in and you get the two same expected values from the twofold, the current state and the way to send to that service. And then you could use it as normal. And this gives you the ability to have both local and global states and even semi-local state where you need some states shared between a bunch of components, but not with every component.
And however, even this, sometimes even though it does prevent massive re-rendering due to everything changes, it could also lead to too many renders too, if one of your components doesn't actually care about a certain part of the state. And that's why there's a new hook called useSelector. 
[13:03] useSelector takes that service or any actor really, and we'll talk about that in a minute, and you could pass in a selector, which takes in that admitted state's value and it returns only the states that you care about. In this case, we only care about the data for the form, so we call useSelector with service and the selector, and we get the data in return. Now, you could still call service.send to send events to the service, nothing stopping you from doing that. The purpose of useSelector is to limit the number of re-renders doing a shallow comparison on this selector.
And also X State is smart enough that you actually don't need to directly compare or shallow compare objects every single time, because X State knows that when you make a transition, if there's no assign actions happening, then it knows for a fact that that state isn't going to change. It could be a lot smarter about that and improve your application performance a lot. Definitely give the useSelector hook a try.
New features in X State
[14:23] Now let's talk about a bunch of new features in X State itself. And the goal of these features is largely to make it easier to specify and type context, events and in the future, a lot more such as actions, guards, et cetera. One of these utilities is the createModel function.
And createModel just provides a nice way of containing your Context. At first it might seem super fluid, but we'll see some advantages to this in a minute. You pass in your initial Context to createModel, And now you have a userModel. This model represents the extended states or the Context of your machine. The machine defines the finite states, the model can help you define extended states, also known as Context. And one of the benefits of using this model is that there are some utility functions such as assign. Instead of pulling assign from X State as a separate action, now you could just call in this case, userModel.assign, and everything is type safe. And it makes it a lot easier to assign values that way.
[15:43] But, like I mentioned, one of the biggest benefits is using Typescript and making it a lot easier to type. If you specify Context and events into this model, now this assign model will actually be strongly typed and you could even restrict the type of event that this assign can take. And this is inferred properly in the machine, right here, you pass in typeof userModel over here, and it will correctly infer the Context and the events too. And this will correctly warn if it's used in a place where the update name event didn't happen, so you could easily restrict it there.
That might be a little bit for both, which is why one of the more recent changes are these events, creator functions, and they allow you to specify the events type and a neat little factory function for providing the events payload. Now notice that we don't have any geneneric types here, and that's because it's inferred from the Context and it's inferred from these events over here. And this is actually really nice because now instead of providing raw events, you could use these as events factories, and have updateName and updateAge for instance, and this is userModel.events, updateName. I probably should have fixed that, but you get the idea.
What's coming up in the next version of X State
[17:20] Now let's talk about what's coming up in the next version of X State. One of the big changes I'm excited about, which is also part of the SCXML spec already, is partial wild cards.
And this allows you to specify transition for any group of events that have the same prefix. Now, prefixes are delimited a dot. In this case, this transition right here will match mouse. It will match mouse.click. It will match things like mouse.move.out. It won't match events like mouse move if it's one word, it doesn't work that way. It's prefix, according to the SCXML spec, but this just makes it a lot easier to group related transitions together or related events really, into a single transition. 
[18:13] Another change I'm excited about is higher level guards. Before, you had to specify guards like if you had some condition, if you wanted that condition to just be the inverse where it's false instead of true, you had to specify a new condition. And now with higher level guards, you could just use these guard creators such as, and, or, or not, and compose them together in many different ways.
There's two benefits to this. First of all, I know what you're thinking, why not just write this in code with if statements and operators like that, and because X State provides you the ability to serialize guards, it works automatically with those serialized guards within the machine, so that you don't have to reference the guard directly. The guard can and should be in implementation detail, and X State allows you to leave it just like that. Also, this allows you to fully visualize these guards in a future version of the visualizer, which will actually show it basically as a flow chart or a decision tree. And that's a really nice benefit of having it specified this way.
[19:40] There's a lot of new changes coming to X State version five. And I'll briefly describe them here. First of all, everything is an actor. Before X State was special casing things like callbacks, observables, promises, other services, and just converting them internally to actors so that you could spawn them, invoke them, et cetera. But now X State version five greatly simplifies this and says, instead of special casing those things, we're taking the stance that if it is an actor or an actor like object, then we could interact with it directly. Anything that has a send and a subscribe method, it's just going to work with it. And it makes it also really easy for you to create your own actors for your own special use cases.
Another change coming is In-order assign(). Previously in version four, in hindsight, this was a bit of a bug, but assign calls are no longer immediately prioritized. Now you can define actions where in a sign call might come later. And so the actions will be reflected properly so that instead of calling assign first, assign is called in order instead. And this is part of the SCXML spec. And it's also technically a breaking change, which is why this is going into the next version of X State five.
[21:15] We've heard a lot that Typescripts might be a little bit painful in X State. And that's because X State is really trying to push the limits of what Typescripts can do. Version five is going to provide a lot stronger and easier typing and better type inference as well. In addition, X State version five is being built from the ground up to be modular and as a result, smaller. You could pull in only the things you need from X State. The internal algorithms have been completely overhauled. And because of the modularity, you could really, really make this as small as you want it to be.
And there's many more improvements coming to X State version five. I encourage you to check out the branch and check out the discussions on GitHub, if you're interested in what's coming next. And the time that this conference talk is aired, hopefully there will be an X State alpha that you could play with.
[22:18] Now, X State has a lot of these benefits of having a visual formalism. First of all, obviously being visualization, but also being able to automatically generate tests, automatically take in analytics and be able to capture all of the transitions and things that can happen and store that somewhere, so that you could do analysis on that later. And also auto generation of things such as testing and type generation and documentation generation, and a lot more than that.
And this is why X State doesn't fall into the normal category of state management tools. It's more state orchestration and it does it in a declarative way to enable all of these things. And that is why I say that we have a visual future for X State because it's a lot more than just being another state management library. One of the recent examples of this is X State catalog, this is actually a really, really great project Matt Pocock, and it allows you just to have this catalog of machines and be able to interact with it directly and visualize it at the same time. And this is the X State inspector, which I highly recommend you checkout too, because it brings new capabilities to visualizing your state and going both ways as well. You can interact with the inspector and have the state change and the other way around. It's like Redux dev tools, but a lot more powerful.
[24:02] When talking about just this visual aspect of code, the fact of the matter is that today a lot of the code we have is very much stuck in code land, where we have code only. And in my opinion, this is hard to work with. We have code that we have to either talk to the developer or read the comments or something, and just try to figure out what this code is supposed to represent, whether it's features or just how the app is supposed to work. And one thing that we could do is have code and diagrams together. But the problem with this is that these diagrams are typically not in sync with the code. And to solve that, we have solutions like code to diagram, where the diagram is generated from the code. But the problem is that it's very much a one way street, whether you do code to diagram or diagram to code. And diagram to code's a little bit worse because it makes it so that you can't really touch the code, but all of these are a step in the right direction in syncing diagrams and codes together.
But the future and the visual future that I see is diagrams and code working together, so that in the future you'll be able to either edit the code and generate diagrams or edit the diagrams and generate code and be able to edit that code as well. We see this in so many different areas in tech, and this is something that I definitely want to bring to the web development world, which is why I'm starting a set of tools called Stately. And this set of tools are going to be really useful for visually creating, inspecting, testing, analyzing, simulating these state machines and state charts for your app. And in the future, won't be restricted to just X States, but will allow you to encompass a lot more logic regardless of what language you write in and be able to share them and to collaborate with other developers and other teammates on it. And if you want a preview of what these tools are and what they could do, go over to stately.ai. So with that, thank you, React Summit.
Questions
[26:45] Nathaniel Okenwa: Are you using state machines explicitly in your applications? And if we go and look at the answers, we can see that most people said, yes, a good 38% said "Yes, with other or no libraries." 28% said, "No, they're all implicit." 25 said "Not yet," but they want to. And 11% said "Yes, with X State." Is there any surprising results there that you see David?
[27:13] David Khourshid: Hey, yeah. At first, I was surprised that we have "Yes, with other or no libraries," because at least a lot of people are realizing that state machines are important and explicitly modeling your application logic with state machines is also important. I'm glad that developers are understanding that more and more. And I hope that my talk inspired them to maybe use X State to just make that process a lot easier.
[27:40] Nathaniel Okenwa: It's always like that. We see a developer principle or something become more important. And then there becomes a tool that comes along and just makes it really easy to use. Definitely I'm going to be checking that out. We've got a couple of questions and I'm going to go through them. I'm going to go through one from Vasiliy Shelkov, "Is X State a global state management library and alternative to Native React state management, Redux, Recoil?" They like the idea of having a clear view of state transitions and events, but not so much of global state as they rarely find it necessary. That's a bit of a long one.
[28:17] David Khourshid: Yeah. X State is however you want to make it. It could be used in a global fashion, but the typical use case is using it in local component state or wherever you need it. Even bringing that up and especially with the new Hooks, now you could share those services through components as you need it. In that way, it functions the same as React's Native useReducer and also Recoil in its actorModel. I do want to say that X State is more of a state orchestration library rather than a state management library. There's a difference in comparison there.
[28:55] Nathaniel Okenwa: Yeah, that makes sense. That makes sense. We also have another question from Lobbian, "Are the send parameters typed? Does code completion know about what send parameters are available?"
[29:09] David Khourshid: Yes, it does. If you type your events in the machine, then you could do send, start typing and it'll be able to auto complete the events as you type them and even have the correct parameters if you type them correctly. In version five, this typing is going to be a lot stronger too. So, look out for that.
[29:28] Nathaniel Okenwa: Nice, nice. We're looking forward to that already. And Armanos:, "Does it support middlewares?"
[29:35] David Khourshid: It does not. And the reason is because middleware is a different concept. Basically you could think of X State as a lot simpler than something that needs middleware, X State is something where you send events to and you subscribe to state changes. Now, when those state changes happen, you could do whatever you want with them. That's where your middleware would go if you want such as logging. But also X State declaratively handle side effects too, in the form of actions. And that eliminates a wide class of middleware that you might need. So yeah, the whole actorModel, state machine model, it doesn't use middleware because middleware is too abstract... Or not abstract, but ambiguous and vague. And you can't predict what goes on in middleware. And the whole point of state machines is to be able to predict everything.
[30:26] Nathaniel Okenwa: Nice. We also have another question, which is, "Can you chain send commands or is there a callback or promise on the send?"
[30:37] David Khourshid: Send is fire and forget. You send an event and then the machine receives it and does something. It's the same as if you tell someone to do something, you're not going to wait for them to be like, okay, I understand. Or maybe that's a bad analogy, but yeah. Send is fire and forget.
[30:55] Nathaniel Okenwa: Cool. And another question from Eric, says, "How does utile handle data changes comparison or do you need to use normalized data?"
[31:07] David Khourshid: What you do with extra data is, you're basically free to do whatever you want. You put it in Context and then you could change it. X State is smart enough to know when you actually change the Context data though. You don't need to do big diffs or anything. And also because X State has the actorModel and you could spawn or invoke actors, those can be little containers of data. If you only want to subscribe to changes from those, you could do so individually without having to do a deep comparison of the entire object. So, yeah.
[31:43] Nathaniel Okenwa: Nice, nice. Now, we've got a question. I really like this next question. Imagine there's someone out there in the audience who's listened to this talk and thinks X State is amazing and they want to expose it to their team. This question says, "It feels like they are quite a few new concepts and probably a harder sell for a development team. Have you got any tips for what a good way of trying X State and getting the team of developers interested in trying X State would be?"
[32:09] David Khourshid: Sure. There is an article I wrote called You Don't Need a Library for State Machines. And that article describes how to just get started with using switch statements followed objects, and just getting pretty far along the path of using state machines in your app without too much friction. In fact, you could use the same useReducer or whatever you want. And then it shows how effort listed is to migrate to X State when you need to.
[32:38] Nathaniel Okenwa: Cool. We have another question about performance. One of the first ones is comparing it to other libraries. Since the poll asked if users were using other libraries, they're curious to know how X State compares with some of the other state machine libraries, and what really sets it apart.
[32:54] David Khourshid: Good question. I actually haven't done too much research on that. There are other state machine libraries, but yeah, I haven't done any performance research there. Actually it's fast enough though, I haven't heard anything bad about the performance.
[33:09] Nathaniel Okenwa: Oh, that makes sense. And what is the performance impact of using React use state directly versus using X State?
[33:16] David Khourshid: Well, there's always going to be a little bit of overhead, which is why I say X State is most useful for complex logic, because it's definitely going to outshine trying to do it manually.
[33:29] Nathaniel Okenwa: Nice. And do you recommend one or multiple machines per app? This is a question from Radoslav.
[33:35] David Khourshid: It depends. It depends on your app's needs. If your machine gets too big, then you should try to split it into multiple machines and those machines will act independently. You could think of each of those machines as just little entities that communicate with each other, which makes it really easy to organize your logic.
[33:53] Nathaniel Okenwa: Thank you so much. We were able to fit quite a few questions in that short amount of time. We're going to have to move on. I'll see you later, David. Hopefully I get to see you play piano at some point.
David Khourshid: All right. Thank you.