Check out a free preview of the full Advanced State Management in React (feat. Redux and MobX) course:
The "Redux Thunk Solution" 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:

Implementing the Redux Thunks to make Redux wrap the asynchronous APIs. - https://github.com/stevekinney/jetsetter/tree/redux-thunk

Get Unlimited Access Now

Transcript from the "Redux Thunk Solution" Lesson

[00:00:03]
>> Steve Kinney: So we're going to implement the Thunk pattern in our Redux application. So this is to simulate a server, that's why we called it API. It's gonna use local storage, but it's just as asynchronous. We're not at this point gonna worry about catching the errors, per se, if there's a network failure.

[00:00:21] Right, ways that you might think about doing that is to just display some kind of error message. And that would be something you'd probably keep in the state and then show in the user interface. But we're gonna assume a happy path, so we can see the pattern in play.

[00:00:36] So right now, it is not wired up, my goal is to get it so that we are saving to the server. I'm gonna start with the adding a new item, that way we have stuff in the database. The only kind of change that I've made so far is I've cleared out those default items.

[00:00:51] So you don't see the defaults in here as well, but we'll add it right now. We'll say Hello, and you can see that it's added to the page cuz we haven't implemented anything yet. But if I refresh the database, there's still nothing in there, and if I refresh the page, it is very gone.

[00:01:10] Right, so this is still the old functionality. I haven't implemented anything yet, just all I've done so far is cleared out the fictitious items that I had in there, previous examples. So let's actually go ahead and start taking a look. Most of the work that we're gonna have to do is in the items actions, like those action creators.

[00:01:28] First, we are gonna need to wire up Redux Thunk, though. So if we go into the store, we check this out, we can see that, we're actually gonna pull in the fancy one we did with the dev tools, so we can see everything along those lines. So give me one second there

[00:02:10]
>> Steve Kinney: And I'll add that to the base branch. I'm gonna check out a live coding branch so I can push up what we work on together right now.
>> Steve Kinney: I'll call it live-coding-redux-thunk, all right.
>> Steve Kinney: Very cool, all right, so we have this in place. So here I have an array for middleware, remember that we're spreading that out using applyMiddleware.

[00:02:44] If we weren't using the dev tool, like their argument would literally just be applyMiddleware, and the arguments of middleware. So you can pass them in as the first piece of middleware, the first argument, so on and so forth. This spread operator is taking that array and spreading it across.

[00:02:59] It's almost like using apply with functions, so we'll have that. We do need to put in redux thunk, so that's pretty easy. We're just gonna pull in the thunk library from redux thunk, that's pretty great. So we'll say thunk from 'redux-thunk', and then we put thunk in the middleware.

[00:03:26] And I don't think I have to say thunk anymore, except that time. And the time that I accidentally say it again. But so now we've installed that middleware, so now we have support for thunks, very cool. So really, the only place we would work with the database. We're not gonna persist the filter actions, we're not gonna persist that ephemeral state that's part of the UI.

[00:03:52] The only state that we're gonna persist is the model data. So let's go ahead, and like most of the work we're going to do, it's going to be in this items-actions. Cool, and so let's get addNewItem going first and foremost. Cuz we wanna be able to put stuff in the database to be able to get stuff out of the database.

[00:04:18] We could get all of them from the database right now. But there's nothing in the database and that's not really rewarding. So we'll start by putting stuff in, and so we have an object here that's pretty straightforward. What we wanna do is, we want to asynchronously do the operation that sends it to the server or puts it into the database.

[00:04:39] And then when that resolves, then we'll fire the action to update the UI. And again, I think we talked about this a little bit earlier. Different UI patterns will work a little bit differently. There's always the optimistic pattern. I think last time we did this, we worked with the optimistic pattern.

[00:04:55] We did the thing, right, and we talked about doing the thing, and if it doesn't work, then maybe pulling it back, right, it all depends. At Sangrad, we have some APIs that could take two minutes, but almost always succeed, so we optimistically update the UI. And then if for some reason it doesn't go right, we can kinda roll it back or display an error, it all depends.

[00:05:18] If you're offline on the Twitter app, you can heart different tweets and it's gonna show them as hearted, I think that is the past tense of that. And if it doesn't work out, they'll go back when you get network connectivity again, so that's a pattern. We're going to put stuff in and then show it.

[00:05:32] But depending on the UI you wanna implement, you might do something slightly different. Very cool, so for addNewItem, we're gonna do this in two steps. We need to add new items, really, the only one where we do a little bit of massaging of the data. Cuz all we have is the value from that input field, and we wanna make the item object.

[00:05:48] The rest of them are gonna be very much just like, wrap the current object, this is the only one that's got a little more going on. Which is we'll say const item is going to be the default of packed. And this could happen on the server, we don't really have server logic per se.

[00:06:05] But this could happen on the server as well, and depends on what your API looks like, really. But I don't really have much of an API at this point, and we'll pass in the value. Cool, so I have an item, and now what we wanna do is we're gonna return,

[00:06:22]
>> Steve Kinney: We actually, yeah, we return a new function. We're gonna return a funk, thunk, not a funk. We return a thunk, and it's going to take the dispatch, and when we do the Api dash, nope. Api.addNewItem, add is the one if I check in here.
>> Steve Kinney: Let's just verify, yep, add, very cool.

[00:06:52] So Api.add, and we'll add that item in there. When that promise resolves, this'll be the item plus a unique ID. So we want the one back from the quote-unquote server. And then we'll just dispatch.
>> Steve Kinney: Let's put.
>> Steve Kinney: That item.
>> Steve Kinney: Cool, I do need to import the API.

[00:07:39]
>> Steve Kinney: Cool, I don't need this unique ID anymore.
>> Steve Kinney: So what I expect to see happen is, we already have the user interface wired up, right. We're just adding this thunk in the middle here. We should say, we want to bring cheese, now we have an error.
>> Steve Kinney: Includes of undefined for my filter.unpackedItems.

[00:08:07] No, all right, let's check it out.
>> Steve Kinney: What's up?
>> off screen: There is no value on it.
>> Steve Kinney: Let's take a look.
>> Steve Kinney: Interested in the states. So items, we're saying that there are no items here when we pull it from the state. Okay, so we're gonna dispatch this item.

[00:08:37] Let's go look at my reducer, I think I might have a branch issue here. So we go to my item reducer, and the item reducer when we add a new item is actually a little bit different. So we'll say item, and that'll be action.item. I could also just structure it off, but I didn't.

[00:08:58] So we'll pull that in, we just change the API slightly. All right, let's try that again.
>> Steve Kinney: It did go in the database, we can see. We can see the cheese is in there, but it's just when we came back when we dispatched the action, it's expecting the action to have an ID, a value, and a pack.

[00:09:18] But really, we nested it under action.item, which had an ID, a value, and a pack. So we changed that a little bit so that was a slight problem. So we'll just add, what else do I wanna pack, wine? We're gonna pack cheese, we might as well pack wine, that's not gonna get me through TSA, but whatever.

[00:09:35]
>> Steve Kinney: That I'm gonna leave, right, I've got a prompt type that's saying, we gave it a string. It's of type number, we're fine with that. Cool, very cool, so what I'm gonna do now is that date.now that I do is gonna serve as a number. The prop type was expecting a string, cuz we were using it before.

[00:09:56] We'll handle that in a second, I'm not worried about it.