
Lesson Description
The "Refactor Cascading Effects Exercise" 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 instructs students to refactor code that handles flight and hotel searches triggered by user inputs into a reducer with events to reduce the number of useEffects to a single effect. By centralizing logic based on state changes, the code becomes more organized and declarative, leading to a cleaner and more efficient solution.
Transcript from the "Refactor Cascading Effects Exercise" Lesson
[00:00:00]
>> David Khourshid: We have a lot of useEffects here and this is all powering this component where let's say that we have a form. I like to call this an I'm feeling lucky page because it automatically chooses a flight and a hotel for me. So if I, for example, want to go to Tokyo and I put a start date and I put an end date, then it's automatically going to trigger this flight search first.
[00:00:32]
And then once it finds a flight, it's going to find the appropriate hotel. And then whenever I change something, so let's say I want to go to Berlin instead, it's going to restart that search and it's going to restart that hotel search and same thing, if I change the date, it's going to restart everything.
[00:00:52]
So yeah, that's an example of a feature that would be cool except the code for it is a little bit of a mess. So what I want you to do is start refactoring this into a reducer with events and then reduce the number of use effects to a single effect.
[00:01:20]
All right, so let's get rid of this use effect chain that's causing us a lot of pain. I don't mean to rhyme, but it just came out that way. First, let's set up our booking state. Because we do, since this is going to be an event and state based approach, we do want to use a reducer.
[00:01:41]
It's not 100% necessary, but it does really help here. So this could be in one of these statuses either idle searching flights, searching hotels, or you know, maybe we have an error state and then we have a bunch of inputs. And so these inputs are represented by everything over here.
[00:02:04]
So we have our destination, our start date and also our end dates. And then we have a few other things to add too where we want to represent the. For instance, the selected flight. And again this should be selected flight id, the selected hotel id and also just an error could be string or null.
[00:02:29]
This again is how I would start out. And you could later use discriminated unions if you want to. So then we are going to actually create the reducer and yeah, so let me just const booking reducer. We also need our actions as well. And so this is something where it's really useful to first play around with the UI and actually see what is happening at an abstract level.
[00:03:05]
Because in this application we don't really have events or we don't have actions or things like that. Instead it's just data changing that's triggering all of these use effects. So the first one we could see is that we're triggering something when our inputs update. So we could, let's just type action here, let's call this input updated.
[00:03:36]
And so we have our inputs over here. And so this would be like the destination, start date, end dates and it could be some of those. We also have the flight was updated, so type or sorry, the flight was. Yeah, so chosen or I'm just going to call it updated.
[00:04:03]
And then you know, we have our flights data over here or the hotel was updated and then we'll just stick with that. So I'm going to put state over here and then we have to actually go through our actions. So if the input was updated, then we are going to return the state with the updated inputs.
[00:04:29]
Now here's where things actually get a little bit interesting. Let's const inputs equals the state inputs and everything. So we actually don't need to do this. Now if we have the inputs.destination and we have the inputs start date and the inputs end date, then we actually want to go directly to searching flights.
[00:05:05]
So this is something that we previously used a useEffect for. So you could see over here we're triggering that whenever we have all three of these things we set issearching flights to true and error to null. And so instead we can avoid a rerender, and we could centralize that logic.
[00:05:25]
So we could even add a comment here that say if all the inputs are provided, then we want to trigger flight search. So when the flight is updated we immediately want to start searching for the hotels, but we also want to have our flight id. And then when the hotel is updated we want to, we want to set the hotel ID and then just go back to an idle state.
[00:05:59]
And so what this is going to do, and I'll just show you the end result is it's going to reduce the number of useEffects we have down to one. And the reason that it's only one instead of all of these four is that now we're basing what we should do next on what the state is, so what the finite state is.
[00:06:20]
So if we go to effects solution page we could see we only have a single use effect. Now we have our reducer over here and in this use effect we're determining what to do based on the status. So if the status is search flights, this is where we actually start searching for the flights.
[00:06:43]
If the status is search hotels, then we search hotels in here. And all of this is based on states. So you can even abstract this into a custom component. Or you could abstract both or sorry, not a custom component but a custom hook. Or you could abstract both of these into a custom hook and it would look something like function usetrip search and you would have this reducer, you would have your useEffect from below over there.
[00:07:15]
So this would be whatever that useEffect block was below. And then you would just return state and dispatch as a table tuple. And then what you could do is instead of all of this, you could just use trip search and all of that logic. Both the states and the effects are centralized in one single hook.
[00:07:46]
So we've eliminated the number of useEffects we use. Everything is declarative, we have dispatches. But yeah, so that's the general idea of reducing chained use effects. So, any questions on that? By the way, the solution in this is not perfect. So I invite you to take a look, see if there are things that can be improved and fix them yourself.
[00:08:18]
But it does go to show how we can remove those unnecessary use effects.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops