This course has been updated! We now recommend you take the State Management with Redux & MobX course.

Check out a free preview of the full Advanced State Management in React (feat. Redux and MobX) course:
The "Adding Sagas to Jetsetter" Lesson is part of the full, Advanced State Management in React (feat. Redux and MobX) course featured in this preview video. Here's what you'd learn in this lesson:

Refactoring the Jetsetter application to use Sagas instead of thunks.

Get Unlimited Access Now

Transcript from the "Adding Sagas to Jetsetter" Lesson

>> Steve Kinney: So let's, let's go ahead, and we'll do that.
>> Steve Kinney: And I'm going to go into the store index. And I'm going to,
>> Steve Kinney: Yeah, let's pull it in. We'll say, import. I'm probably not gonna go all the way with this, because I'm gonna need the saga in place first.

[00:00:33] So I'm actually going to hastily abort that decision, now that I think about it. The first thing I really should do is I need to separate this out into two different actions. Like right now, the thunk combines the, hey, you want us to do this thing, and I'm gonna resolve cuz it's done.

[00:00:50] And we wanna say, they click the button to go ahead and initiate the fetch, and now we've got all the items and we wanna do the thing. So effectively what we're gonna do is we're gonna unthunk this. That's a new word, you're allowed to use it. So let's go ahead into item actions and here we have a thunk from earlier.

[00:01:09] We're going to start by unthinking it.
>> Steve Kinney: It's not really getting all the items anymore. So we will rename it.
>> Steve Kinney: Let's call it, or we'll call this one updateAllItems.
>> Steve Kinney: Which is we've gotten them at this point, we wanna update the UI.
>> Steve Kinney: Naming things is hard.

[00:01:41] All right, so we've got the updateAllItems, and that's gonna get the items passed to it. All right, so here we are back to a totally normal action creator.
>> Steve Kinney: So the other thing we need to do is the other side at that, which is, hey, the user in this [INAUDIBLE] we're gonna do it from the store itself like we did in the previous example.

[00:02:05] But like theoretically there could be like our refresh button or some kind of user request. But we're gonna have the one that triggers the request itself. This one I may call export const.
>> Steve Kinney: Fetch item.
>> Steve Kinney: And fetch item just wants to get all of them, right? And what it's gonna do is it's just gonna be,

>> Steve Kinney: I'll just call it fetch. I don't have a constant for that right now. All right, so now our actions is back to totally synchronous. You know what we just got back? Easy testing, right? We just won back easy testing for our action creators, which is pretty cool.

[00:02:53] That said, this doesn't like do anything anymore. Now it just dispatches some actions and this one isn't even technically in my reducer. So like [LAUGH] this one can get called all day, nothing's gonna happen, so that's nice. Let's actually to ahead and before we hook, like I'm really, I want to hook the saga up to the store, but I don't have a saga yet, right?

[00:03:16] So I'm gonna go ahead and make a saga, that seems the responsible thing to do. Make a saga.js. All right, so I need to pull in some of the helpers.
>> Steve Kinney: And so what I'm gonna do is I'm gonna import. If you remember, all was like all of the different events that you wanted to listen to.

[00:03:38] And we have call, which is go ahead and make some asynchronous requests, and then kick off the generator when the promise resolves. Put is dispatch a new action, and takeEvery is basically a listing for all of these events. And this is gonna be from redux-saga/effects.
>> Steve Kinney: Because these are all side effects, they're not things that are gonna passed in, they are things that are happening outside of the function that were kind of tuning into.

[00:04:09] All right, and so the other thing I want to grab is that API, quote unquote that we had before.
>> Steve Kinney: Api from ../lib/api. All right, so we have that. And we do want that update all items. The update all items, remember, we received from the network, we want to display it in the UI.

[00:04:32] So we're gonna need to like, when we've received from the network, we're gonna need to trigger that action, so we import the update all items.
>> Steve Kinney: ../action/items-actions. All right, very cool. So now we have, like remember like in react, we have that one place that's we start. The application component, the provider component.

[00:04:56] We need that starting saga. So conventionally you should call it Root Saga, call it whatever you want, you shouldn't but like, and that is a generator.
>> Steve Kinney: Root saga, and all that's gonna do.
>> Steve Kinney: Is it's gonna call a fetch items from API generated that I have not written yet.

[00:05:27] So let's go ahead and do that. So export default, all right. So all of a sudden we receive a fetch item action. We should probably fetch the items, right? So export a function we will call fetch items from API.
>> Steve Kinney: All right, and what that's going to do is,

>> Steve Kinney: It's going to go head and it's gonna take every,
>> Steve Kinney: Of the fetch items. Actions get fired. And it's gonna make an API request, which we will also have to write. And this is kind of cool if you think about it, cuz it's effectively waiting for future things to happen, right?

[00:06:25] This is like, looking into the future. Like when these happen, I want to take that and handle it, and pass it over to this make API request. So it's kind of like looking into not only asynchronous, but it is also constantly waiting and observing the state of our application.

[00:06:43] All right, we have one more to make and that is our,
>> Steve Kinney: Make API request that we saw earlier.
>> Steve Kinney: And with most things a sync, the reason we have to make so many generators is once you're a synchronous, that's a way of life for you. It's mixing a sync code and synchronous code is always a recipe for sadness, so we tend to want to avoid that whenever possible.

[00:07:09] So here we'll say the items. And again, if you've used a sync wave before, this will look familiar, like I'm normally used to typing await here, but this is user generator, so we'll use yield call to Api.getAll.
>> Steve Kinney: So we'll pause, we'll wait for that promise to resolve.

[00:07:31] We'll take the result of that promise, and we'll pass it to the items variable. And then we can go ahead and hand things back off to the very like normal plane object redux world, right? We've separated out all of this squirliness from that very pure and simple redux that we got used to in the very beginning.

[00:07:53] We'll go ahead and yield and we'll put the updateAllItems with the items. All right, cool! So now we have saga. We have those very simple actions. All we need to do is take this saga and install it as middleware in redux.
>> Steve Kinney: All right.
>> Steve Kinney: We're gonna leave the thunk in here because the rest of my app is thunks, and I'm not gonna be hasty here.

[00:08:27] So bring in create saga middleware from redux saga.
>> Steve Kinney: And cool, and so then we'll also import that saga file.
>> Steve Kinney: So now we have the ability to create saga middleware. We have the saga file. Let's go ahead and create that saga middleware. Let's do it after the imports.

[00:08:58] I don't want to get yelled at.
>> Steve Kinney: And we'll say saga middleware let's create saga middleware. And the last thing to do is put it alongside its buddy. Remember when we cleared that logware before and each piece of middleware was responsive for kicking off the next piece of middleware, right?

[00:09:18] We're taking advantage of that here. So they can live happily together. And finally, we can comment this out, because that thunk doesn't exist anymore. We unthunked it if you recall, and so we'll say saga middleware.
>> Steve Kinney: SagaMiddleware, and kick off the generator.
>> Steve Kinney: All right, here's it's open.

>> Steve Kinney: Nope. All right, I'm gonna take a-
>> Speaker 2: [INAUDIBLE] Saw how you created action? The yield all.
>> Speaker 3: Yeah, yield all.
>> Speaker 2: The rootsaga [INAUDIBLE].
>> Steve Kinney: Yeah, I was like, I'll do that later. The thing about promising to do stuff later is that you actually have to do it.

>> Steve Kinney: All right.
>> Steve Kinney: I'm gonna go back and take my five minutes.
>> Steve Kinney: So we're not getting to the point where we make the API request. So that's the next thing I need to handle.
>> Steve Kinney: What is it called now, fetch items?
>> Steve Kinney: If you don't ever fire the action, it's not gonna happen, right?

>> Steve Kinney: Let's verify that before we get really confident that it was something so simple. Like we're all like, yeah, yeah, that's what it was. I'm even like, that's totally what it was.
>> Steve Kinney: So we're really excited and we implemented everything and then we refreshed the page and it didn't happen.

[00:11:41] It was everyone's favorite kind of debugging where no error is thrown. And you just have to basically try stuff out until you find it. And what we realized is that originally we had this.
>> Steve Kinney: Which is we dispatched the event and then we started up the saga generator.

[00:12:02] So that event was long gone. By the time the saga generator started, which meant everything theoretically worked. But if a tree falls and no one's around to hear it, does it actually make a sound and stuff along those lines. So if we swap the saga, make sure that we start the saga first and then we swap over.

[00:12:26] We'll see that we actually have everything from our database. Full disclosure, that also happened when I was practicing. And you'd think [LAUGH] I would have been a little quicker on that one. But, yeah, so order is really important. We wanna make sure that the generator is running and taking every one of them before we dispatch it, right?

[00:12:44] And this is unique in this case, right? Because this is when we're doing directly on start up. If we had moved this to componented mount, we'll the store would have started up, the generator would have started up, and then the component would have mounted and we wouldn't have found this issue.

[00:12:57] If this was based on a user event, this wouldn't have been an issue that came up. But it's like in this unique situation where we are immediately dispatching one. That we find ourselves which is in order of. It's interesting for something that is in a synchronous code and pulling events from the future.

[00:13:14] We can pull them from the future, it's from the past that is the problem. Cool. So at this point we've got a basic saga architecture.