Advanced Redux with Redux Toolkit

Typed Custom Hook for useDispatch

Steve Kinney

Steve Kinney

Advanced Redux with Redux Toolkit

Check out a free preview of the full Advanced Redux with Redux Toolkit course

The "Typed Custom Hook for useDispatch" Lesson is part of the full, Advanced Redux with Redux Toolkit course featured in this preview video. Here's what you'd learn in this lesson:

Steve adds type support to the useDispatch hook. A custom hook is created to apply the type. The Redux DevTools extension is also demonstrated in this lesson.


Transcript from the "Typed Custom Hook for useDispatch" Lesson

>> There is a version of this that is very similar for dispatch as well that we can look at. Easier is a strong word cuz other than grabbing something from the library and using it, which is getting the type of the dispatch is a very similar endeavor. I don't want to select you're gonna go into store, sorry.

And this will, since this is based on the output of Git state, it will automatically stay current with your state management. So application dispatch. And that is simply Type of Right, so this is the one that's bound to the actions that you're currently accepting, so on and so forth.

So this is the type of your state, this is the type of what we are kind of taking and ready to go at this point. So we'll also add a hook for that too. And that one we don't need a custom type cuz this is the type. It's cuz we know that used all, like used dispatch does is gives you a copy of dispatch that you couldn't import cuz you made it in a component.

So we've got that ready to go, and that's just gonna wrap useDispatch. So it's one of those things where you can make these effectively once. What do I got here? It's used here, you sure angry about one type argument. What did I miss? Take a look at my store again.

>> Should that dispatch?
>> I've grabbed the one from React instead of, [LAUGH] autocomplete failed me, a lot of things that start with R, I grab the dispatch from React instead of the one from React Redux. So happens when you're talking and you're typing. So we want the one from my store.

We want the one from here As well. Cool, so grab Cool, still angry with me.
>> Are you still updating part of useDisptach?
>> What's that? Thank you. That's why you code with your friends. It's like pair programming on steroids, right? Cool, so we've got that in place and now I can use these everywhere.

So I think we already used the AP selector earlier in the task list, and now we just gotta go put the other one in and create task, right? Cuz this one if you look, it's like it takes any action, like, that's not what I want. This one takes the actions that I know about.

Let's verify that this is wired up correctly first. We'll go back to that first app. And now we have a task that is set up. We've got our initial kind of state management piece kind of wired up and ready to go. And that is kind of in place.

Just to try one more thing, let's go ahead and remove a task. And then after I remove a task, you have a few minutes to just type. To try your hand, I will push up this branch which will have kind of adding a task, removing a task, and showing the tasks.

And I'll put the branch up and then you can kinda use that as inspiration for how would this look like on a user, right, which is effectively the same pattern just with a different data model in this case. So we'll give it a shot. But let's actually let's get to the point where we can go to individual task and we could remove it in this case.

These are still pulling columns and stuff from the context API. So we'll leave those in there. We will obviously get rid of this one when you do your job in a little bit, or at least when I solve it afterwards. Cuz even if you write it, it will not be in my code.

So I will also have to join you in that endeavor. But if we wanted to get that useDispatch or useAppdispatch in this case, useAppdispatch. Awesome, and we've got that ready to go. And so now simply, now anywhere in our code base. This is a sales pitch for just regular Redux right here.

But one of the things I really love about Redux is, I just have these dispatch actions to say stuff happens. Everything else is like, my view layer is really a view layer at this point. So we've got that in place. And now I just gotta find this Remove button over here and we'll say, onClick.

And we'll call dispatch. I don't think we fully implemented roof tasks yet, but where's my autocomplete? Did I explore it, let's see. RemoveTask gets in there. Cool, removeTask, that takes the payload. This point is undefined, which is again TypeScript working for us. So let's make it angry, and then we'll make it happy.

How's that sound? But in the room, you get to decide, should I make it just take the ID, or does it take an object with the ID key in it? You get to decide my API at this point. Whatchu wanna do? Should we do id equals task id, or just passing the task id?

>> In this case, I just passed an id.
>> All right.
>> That's what I have in my notes. So let's do that. I always have two minds about it. So I get the red squiggly, which makes total sense cuz, again, the system works. So now in here.

And now this is the tricky part because I feel like for me, this is a personal opinion time. You can put that like some [LAUGH] stars and rainbows, personal opinion time. For adding stuff and stuff like that, I love the fact that I can treat things as mutable.

For removing, I'm so used to just filtering things that don't match the ID that we're gonna have to do this one together. So we'll go ahead and we'll try it out. And what we need to do is, so we've got the state. We've got action, right? And that action is going to be what these payload actions.

And this case, this is we just said that it was going to be the ID that is a string as we. Now I could grab it off, I've two choices. IDs are pretty safe. If that makes you uncomfortable, you could do task id as well. Guess what that is, it's a string.

But if your IDs ever change to a number, this will all be correct, which is nice when you're refactoring. For other properties, all the different properties, stuff like that, then have TypeScript tell you, hey, 17 files away, there's an issue, it is nice. IDs are a pretty safe one.

And we'll keep this one for now, though. Awesome, and so now, in this case, really the standard practice is to do this. Say, state.entities.findIndex. And then probably after several years of, I could have done the entire task too, right? After several years of being told that everything should always be immutable at all times, you have to figure out how to mutably remove a task from an array.

Cool, so let's take a look at that. So this findIndex takes a callback like most of the other array methods. And we'll say, find the index of the one where the task ID equals the payload, in this case. So we'll get the index for that, and that's a number.

And what we'll do is we'll simply say, From that index, and remove one from there, state.entities. Could you name this task? Since it's scoped to tasks, you absolutely could. I have done it both ways, I don't know which one I like more. So if you had a strong opinion, now, I think it should be called task, I will give you the permission structure to go do it.

I waffled back and forth multiple times when thinking about which one I wanted to do today. I went with state in this case mostly to make it clear that this was the Redux state for all y'all. But you're welcome to just call up the thing in this case too.

What you do on your own is totally cool. So let's verify that this all works, and then I'll push it up. I can load in those the same way as loading that data before I can load it as the initial state as well. So we'll probably do that in a second.

You can add it. Let's say, nope. So this is where having the Redux DevTools comes in handy. So let's take a look. We can pull those up. So we add task. The nice part is, and if you don't have the Redux DevTools, I'll also drop a link. We'll put it in the notes for later, which is it shows you a running log of every action.

This is one of the things. A question I a lot of times get is, well, there's useReducer now in the context API. Do I need any of this stuff? Well, yeah, maybe you don't in a lot of cases. Nice parts include, yeah, a lot of this tooling that we're seeing today, kind of built in.

Other nice things are this Redux developer tools which will show you the running log of every action that has happened in your app since you kind of loaded it again, and let you go back in time and see things. And you can also export the current state, right, with these buttons down here and then also load up a fully hydrated state of the application.

So it's nice especially if you have, it's hard to get a full JSON from a consumer customer. But I feel like you have QA or something like that kind of going through, and they find you to be able to load up the entire state and triage it. Makes total sense.

But I can see that I'm literally just not getting an action here. I don't have to do the whole thing of like, let me throw a console log in there. And see, I can literally just figure out, okay, it's definitely not firing. So let's take a look at the code.

If I find out the issues I didn't save the file. I'm gonna be. All right, we've got that. I'm gonna guess that red squiggly under dispatch means. I You can call an action creator, and it will make an object. You can absolutely do that. If you don't dispatch that object, it does not enter the store.

Luckily, tooling is nice. So now we get to demo the Redux DevTools, all right, that sounds like a chapter. Now we get to demo the Redux DevTools. So now you can see, there it goes. As soon as I dispatch the action, we'll do one for order as well.

And the nice part is, I can see the action. I can see the state during each one of those. So initially, we had tasks as entities, we added one, there it is. We removed it, it was gone again, we added it. And just cuz I'm showing off. I can take this timeline and scrub back and forth through the entire interaction model with the app, right?

[LAUGH] All right, here's a tool that's been here for a really long time. But the nice part is, we get it for free. I didn't set that up, right? I use configure store, so I guess I did set it up from Redux toolkit. But I got it completely for free.

Normally, I am not gonna do this, but you can go treat yourself into the. Cuz you install the extension, it puts this underscore all capital letter thing onto the window object. But first you have to check it exists cuz we tried to call it as a function, and it was a lot easier.

I'd have to do anything,
>> Is it excluded from the production bill?
>> Yeah, it is not included, yep. All of that is kind of built in ready to go, yep.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now