State Management in Pure React, v2 useThunkReducer Hook
This course has been updated! We now recommend you take the React Performance course.
Transcript from the "useThunkReducer Hook" Lesson
>> I checked out a branch called asynchronous actions. And that was mostly to get us back to a firm starting ground again. And there's just some subtle differences. Cuz what happened before is we had to do that line where we looked at the response we saw, all right, if there's a response, and that response has characters, so on and so forth, right because we wanted to make it generalizable, we use fetch functionality, right?
[00:00:27] Which meant that there was a certain amount of leakiness to that abstraction. We talked about the fact that we could pass in a function. We talked about a lot of things. We had big hopes and aspirations. We're gonna try a little bit of a different approach, kind of based on that thunk stuff that we were talking about before.
[00:00:40] What if we could dispatch an action and say go fetch stuff? This is what you need to do, and then let the reducer handle all of that setting the loading, so on and so forth. So this is kind of checking out that branch gives us another firm starting place to start with.
[00:01:02] And so we got the action type loading. At this point, I am going back to just, this is going to be a reducer for managing characters, right? We're gonna separate the asynchronous parts of our application from the synchronous state management pieces, right? We're just gonna separate them, that way, they don't have to know about each other which, in my argument, will make more modular code.
[00:01:20] But if you like the other approach, you can use that one as well. And there can be argument why both can exist. So we've got loading, and we've got response, complete an error, nothing dissimilar, and I'm returning the entire state. And what you'll see here is I'm using use reducer right now, and then we can pull just the characters off of that state.
[00:01:40] Now, what I would love to do is, the fetch stuff isn't here yet. What I would love to do is dispatch an action that is a function right, that can undo all of the asynchronous and synchronous, then just patch the real action. This is very similar to how Reducer stan works, instead we are going to write it ourselves.
[00:01:59] And what I would love you to pay attention to is this, we are gonna solve an asynchronous problem, if you wanted one that did login, okay, ke the same approach works. This is simply to wrap this idea of reducer with additional functionality as we need it. So we'll make a hook and we'll call it const lets call it useThunkReducer.
[00:02:25] And I alluded to before, there are ways that you can make< there are hooks for that that will load additional middleware. We're just gonna do the simple possible one, cuz it'll get really into the weeds, otherwise. And it'll have the exact same API as useReducer, cuz it's just gonna be an abstraction on top of it.
[00:02:40] It's gonna be a superset of features. So I'll do reducer, and I'll take an initialState, And at the end of the day is going to, like I said, it's an abstraction. So go get state and dispatch equals useReducer. From whatever reducer they passed in, and whatever initial state they passed in, and that was the bottom of the file.
[00:03:19] And then we'll return that state and dispatch. So all it does right now is this know It basically takes what we got from useReducer and passes it through. Remember when we wrote that first reducer and all it did was take the state and return the state? That is effectively what we've done here.
[00:03:37] What we wanna do is create something over the dispatch function that says, hey, if this is a normal action, just like we had before, yeah, yeah pass dispatch to do the thing. If this is a function, call the function, right? Give it a copy of dispatch and say, hey you take care of dispatch, and whenever you are done doing whatever you are doing, you can go ahead and dispatch actions yourself.
[00:04:06] Right? And so this is the whole thunk thing that we're talking about before. Like I said, trying to explain a thunk probably takes longer than actually writing the code. I aspire to prove that to you. So what we'll do is, we will make a const called, let's call it enhancedDispatch, we could call a thunkDispatch, you can call it whatever you want.
[00:04:27] I'm gonna call it enhanceDispatch and we'll take an action, and again if we still wanna take this no-op, it would take the action and it would dispatch the action, all right. So so far we've given ourselves some hooks in here where we can step in and do some conditional logic above where my cursor is highlighted right now.
[00:04:48] But right now, its just taking the action and dispatching it and what our new asynchronous is gonna do is that its going to, yeah, set up a reducer, wrapDispatch and its enhanced version where you can add an additional logic. And them it will give them state in this enhancedDispatch, which in a normal streaming things will just do the normal thing.
[00:05:10] I could swap this out right now and it would work. But in here is where we can start doing additional things. Now if I wanted to log, if I put a log in here, let's just do it. Now, this works like useReducer except it logs every action that flows through it, right?
[00:05:34] So you could do something like if node environment is development, log the action. All right, that would do the trick right there and it would log every single one. Probably, you don't want that, I mean, you might want that. Or it might be some other flag or something along those lines.
[00:05:50] But we have an abstraction over useReducer to do more complicated things. What we're gonna do is say, hey, if this action is actually a function, pass it a copy of dispatch, and call it. So we'll say, I'm gonna pull in is function, you could do type of equals equals equals function as well.
[00:06:21] And so we'll say if IsFunction cuz give me call the action regardless. But if this action was actually a function instead of an object, then what we gonna do is we gonna call it like a function and past the copy of a dispatch. Otherwise, just do the normal thing.
[00:06:51] And so now we actually have full func support in our reducer, right? A normal action is an object, do the thing if we dispatched a function, call the function with a copy dispatch and let it do the thing. So it's again a function that returns a function.