
Lesson Description
The "State Flow with use(), Stores & Effects" Lesson is part of the full, State Management at Scale in React & Next.js course featured in this preview video. Here's what you'd learn in this lesson:
David discusses a pattern in React where, instead of using context, developers can utilize the use hook to pass context directly. He also discusses the performance implications of using context in React and advises on organizing state machines pragmatically based on specific needs before abstracting into generic solutions.
Transcript from the "State Flow with use(), Stores & Effects" Lesson
[00:00:00]
>> David Khourshid: Hopefully if you learn anything new and Cursor hasn't learned this yet, but let's say that we want to grab dispatch from the context. You actually don't need to use context, you could just use. We have a simple hook called use and then you could pass the context directly in there.
[00:00:18]
This is one of those small patterns that's definitely going to be the modern way forward for React because not only with context or with some cached state, there's a lot of plans for use. But another thing that's coming up is the ability to use a store. Again, that's in the future for react, but it's a pattern that I want you to get used to.
[00:00:43]
You don't need to use context, you could just use use. Awkward to say that, but you get the idea. So now on click. We could actually dispatch that search. So this is going to start the search. The state is going to transition to a loading state in which we show this loading view and then we will see this results view.
[00:01:07]
And then we also need dispatch over here. So we're going to grab that from the context as well. And then we're going to just have the ability to go back. But we also need to grab the states here too. And here's where it gets a little bit interesting because we have state results map.
[00:01:31]
And so here's the first thing we know, or at least we expect reasonably that results should exist. But it says here that it might be undefined. So this is where, you know, we might want to use type states. And so what we could do is say if the status is results, then the results are definitely defined.
[00:01:56]
So I'll just leave that over there. And so we could split this up even further. We could say that, you know, we have a loading status and then we have a search status over here. And just like we did before, we could combine this so that we have our common properties such as results stringer undefined and then we have our discriminated union.
[00:02:28]
So you see over here with our received results we already get a type warning because it's like, hey, wait a minute, you're going to the results page, but you're not actually adding any results. Again, this is one of the great benefits of using these discriminated unions, AKA type states, is that it will tell you, hey, you forgot to do something that adds the results to the state.
[00:02:54]
So now we could add that. And this is just going to be action results. So now we could go back up here to our results view and potentially get rid of that. But it's still erroring out. And the reason it's doing that is because it assumes that this is any one of the three possible states that we could be in.
[00:03:18]
So what we could do is we could say if there are no results, we could return null and hopefully we never get here. But you could also just show some sort of error. This is something that I don't expect users to really do anything, but you could just say error, something went wrong, and then maybe you'll have a back button or something again.
[00:03:45]
This is one of those impossible states that we should never be able to get to. Okay, so we have our state, we have our dispatch, we're putting them in a FlowContext provider, and there's one more missing thing actually getting the results. If we go back to this state machine over here, State machines have this concept of actions.
[00:04:13]
One of the actions that we could do is an entry action for the results. And so we could say, sorry, it would be over here. So we could actually add an action and we could say in this state, we should load the results. So this is what I mean by a declarative effect.
[00:04:34]
We're declaring that in this date, whenever we enter this date, this is where we should load the results. So without getting into X data or state machines, let's see how we could translate that to this application. This, this would be a good use case for useEffect. Essentially, we're saying that when we're in the.
[00:04:56]
Not the search page, but the loading page, we should be fetching those results. So we could, let's just do await new Promise a timeout. So we're just doing a. Or actually [LAUGH] It's another weird thing about React. But we do need to. It's a little bit tricky to use async await inside of a use effect.
[00:05:24]
So we'll either do this or you could just put another function inside there. It gets pretty awkward. Honestly, my favorite thing to do is use Promise then because we've been doing that for years and that's the most natural pattern inside of user effect. Anyway, the idea is that we are going to dispatch the results result one and result two.
[00:05:46]
And the thing that I really like about this is it's based on the state. So if the status is loading, we know we have to do that effect. So we're not, you know, we're not going based on a Boolean variable or even multiple different states, you know, states or variables.
[00:06:06]
Instead we're just going based on this single state status. To actually start this now of course we need to do proper cleanup, and this is where AI coding assistance can help. But now let's see if this actually works. So going back to our travel flow, if we reload, there's one thing that we forgot to do.
[00:06:33]
We forgot to actually conditionally show each of these components. So the way we could do that, and this is another reason why I like using these finite states, is that this becomes very, very clear. We have if state status is search, show the search view. If it's loading, show the loading view.
[00:06:53]
If it's results, show the results view. The other way that this is typically seen in React apps is you have a long list of conditionals like if is loading and results length is 0 or whatever. So basically you're going based on implicit states rather than these explicit states.
[00:07:17]
And so now that we have this, let's reload. It says search for stuff, click search, it's loading, and eventually we get the results. So we could go back and then we could search for stuff again. Now there's one more thing that we could do. This is all contained within the page, but we could clean this up a little bit again to make the code a little more understandable.
[00:07:42]
What we could do is we could create a, let's call it flow provider. And of course it's going to take children, which is the react node. And so we could move all of this logic inside of our flow provider. So we have it up here and then, so then we have our flow provider here and down here, quick.
[00:08:15]
>> Speaker 2: Also, the state status would be for results would be results received right down below, unlike 143.
>> David Khourshid: Let's see what we have here. I think it's just results. So the action is called receipt results. And then we show results. Not the best name, but yeah. Okay, so now we have this issue over here where because all this is contained within the components.
[00:08:48]
Now we don't have the state directly, but the easy way to solve this is we could have another component called function flow content. And from there we could use that flow context. And then we could just put all of this inside of there. And then we have our flow content.
[00:09:08]
So this looks nice and clean. So does this. And we have everything encapsulated inside of this flow provider. And so now we see that everything still works. So you basically just made your own redux. Okay, I see in the chat Sandeep asks, does using use context? I mean, it's use now, but same thing, use context.
[00:09:35]
Does it have any performance implications? The short answer is yes, it does. What's going to happen is that with use context or with using the context whenever the state updates, pretty much everything under there is going to rerender, unfortunately, and this might not be a big problem if you have state that infrequently re-renders.
[00:10:02]
So context is essentially the built in React tool that lets you share this dates and share a way to update the state with other components. At least at the moment there is not really another I mean there might be, we'll talk about that in a future lesson, but not really a built in way of doing what Redux or Zustand etc do those libraries really help you narrow down the state, or at least the part of the state that each component expects so that you're not unnecessarily re rendering.
[00:10:37]
But again, for basic apps or apps where the state doesn't change too much, this is more than sufficient. It's not really going to cause many performance issues, but it is something to definitely be aware of because it definitely can happen. Like for example, if you have a timer running in there and you have this reducer that changes every single second, yeah, that's going to cause a few issues.
[00:11:03]
Or if you have something that's keeping track of the mouse position or any sort of fast paced subscription, then yeah, that's going to be an issue. Lucas also asks in the chat, how would you organize these state machines like a generic step state machine or a state machine specific for booking flights?
[00:11:22]
My advice, at least in my experience, is to be pragmatic first. So don't try to go a level of abstraction beyond what you're working in just yet. Always do the manual thing so you have a state machine specific for booking flights. It might be just a very simple step by step sort of multi step flow, but don't try to abstract that out into some generic stepped state machine just yet.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops