Advanced Redux with Redux Toolkit

Using Custom Hooks from Redux Toolkit

Steve Kinney

Steve Kinney

Advanced Redux with Redux Toolkit

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

The "Using Custom Hooks from Redux Toolkit" 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 demonstrates the custom hooks that Redux Toolkit automatically generates from services created with the createAPI method. This makes it possible for the service to be integrated with a Redux application or agnostically with any other infrastructure.


Transcript from the "Using Custom Hooks from Redux Toolkit" Lesson

>> Before, you saw that we kicked off that thunk ourself, and you could do that. What I'm gonna kinda do is show you that to make the point of other than the fact that is using a Redux store under the hood, you can do this stuff agnostically, or you can integrate it with your current infrastructure.

Either one of those are acceptable options, in this case. So let's go back into our API servers for a little bit. And what's kinda cool about this is I can go in here now. And let's say, for instance, I wanted to export const. Export const = taskapi, we'll see what we get the autocomplete with item API.

[INAUDIBLE] I was originally gonna do this in the other app, but I decided why not. So we'll say, Check this out. All I did was define an endpoint. The autocomplete there are two premade react hooks ready to go, right? So these are hooks that if you've ever used swr, or anything along those lines, that will go and give you, you write your own custom fetcher, and you pass it in, all that kinda stuff.

The really cool thing that this will do is it will generate the hook for you, right, that you can export and have. And you can then pull this in anywhere. As soon as you call that, you get everything automatically and for free in your application. So let's go try it out.

Let's go into our components. Let's head over into application. I guess I could do it in the individual items list. But let's go ahead. Let's make one list for now. And we'll do stuff with it, cool. And so we'll say is const, let's do our use, ItemsQuery. What do we have in here?

We've got a whole bunch of stuff. We've got data. There's data and there's current data. One is what is the last thing it had? One is immediately have or nothing, in this case. We've also got isLoading, excuse me, all the states. This is really cool, because to your point before, where we were like, so we set it.

And then when it fills, we unset it, and all those things is like, those abstractions are done for you. So here you've got isLoading, isSuccess, right, which might mean isSuccess, it's good. isUninitialized means we have never even tried to load this, right, which could be interesting. isFetching is different than isLoading.

And this is where I was like immediately like, yo, sold, which is this how it goes for me every time. I need a loading indicator. I show my loading indicator. You'd think I'd learned at this point. I show my loading indicator. And then eventually I'm like, you know what I should do?

I should update, eventually, this data. And then I have to deal with the state of the array. I already had the first set of data. And now I'm loading more, and then I accidentally show the skeleton loader while I'm working on it again. And then I have to come up with this new state, which is we have data and we're loading more, which is a different UX than we're loading data for the first time, right?

And this is automatically handled for you. isLoading is only called the first time it's loading the data. isFetching, it's called the other times that it's updating the data. So instantly you know if this is an update, or whether or not you're loading, and all of that is built in for you and handled, right?

And again, I'm using a React application, and I'm getting the React hook for free, but it's completely framework agnostic, right, cuz you're gonna have all these things kinda built in for you ready to go. And so we gonna can pull in isLoading in this case as well. And I really just want the data at this point.

And we'll see an interesting problem we have to solve for in a second, which is, yeah, that could be undefined, right, if it's not loaded yet. But we'll get the isLoading. And again, because I'm using mirage, I'm just using the rest serializer again, I know that it's going to be, I said it was tasks.

But I also know that I need to deal with the fact that I gotta get that object key and stuff like that. I can do that with my UI, we'll see how to transform stuff, or select stuff and a bunch of really cool things around that. But let's just handle it in the most silly way at first, and you can find out different stuff along the way.

So here we'll say, in fact, let me actually just change the type, cuz a slightly line at the moment. So this is items with an item, and it will deal with it in other ways later. Cool, and then so what I would seek to do is say that let's do the most straightforward thing at first.

We'll say that items, and we will fix this. UseMemo and just, Or give me an empty array, that way I don't have to deal with maps and stuff like that, awesome. And you can see my typing holds up. All I had to do at the very beginning is say what it was.

I guess you'll notice that TypeScript put that question mark in there for me for my safety, but against my well, right? This is a reasonish syntax, which is if you've ever had to do data.items or data if it exists, then data items. Or this and or that and do a set of conditional statements on the way, the question mark will handle that for you.

And we can have this in place, and now we can pass this in. So we've got items, it's not assignable, ItemProps. Let's see what I decided. I just took that out, cuz I don't wanna get yelled at TypeScript at that moment. Cool, that's passing ideas off to transform then a little bit, but let's actually pass in a full item right now.

Awesome, so we'll see all that in a second. All right, and then we'll go down into the item and get that ready. Cool. Check that out. Oop, item. I'll look at my type in a second. [INAUDIBLE] But we'll see. Awesome. What you mad about, let's see my types.

I might have to glance that, cuz I'm not quite sure why it's so angry about that, but we'll see.
>> Structuring item into item, I don't know.
>> What's that?
>> I don't know this is right.
>> It's declared again on line 10 there.
>> On this file?

Yeah, that's the hard-coded one, but it should still be. That was enough. Thank you, live coding friends. Yeah, the still render while I don't have data protections that I put in for myself beat me late in the day. That's always lovely. Now we'll pass them in. Awesome. Cool, awesome.

What you mad about? If I don't say files changes, this don't matter. I installed that, right? Give me a second. I'll work this out, and then we'll pick it up from there. Y'all watched me install that, right? I just need to restart the server, awesome. So despite last minute refactoring there, and the fact that if you don't save files and restart your server after NPM install stuff, you have a few issues.

But with an automatically set up hook, I kinda get everything in place out of the box. And setting up, I wanna show you that why I'm interested in it mostly in the way I have a few features built in it right now. That I'm kinda in a proof of concept, is that the fact that I then get all of this in the tools, and I can mostly am in the process of swapping out a bunch of pieces of this, I can kind of see that I'm getting.

All right, the middleware is registered, I'm getting the pendeen ready to go. And this is for all the items. I get the status of failed, all of these things that I can then work with for the rest of my existing infrastructure. But then I get a whole bunch of functionality that for free.

So for instance, I can do stuff like if I go into the hook, there are a bunch of options that this will take. So first it takes just what was the thing you were looking for? And also refetch the data on an interval of every 120 seconds. I'll do something shorter so we can see it, but we have this in place.

And yeah, we can put a loader up too, cuz that's fun, just put an easy one in here.
>> But this is only supposed to show up once, right?
>> Loading should show up once. isFetching should show up every time. And the fact that I don't have to do all this anymore is wonderful.

Cool, so let's say I don't need to style it, we'll see, it will be great. Let's shrink these tools just a little bit. Now, those rerenders are showing you that it is rerendered every time. Where did my loading go? But if I look at the tools, did you see that I am getting, cuz I set it to something ridiculous so that we would see it loading the tools, but I'm automatically getting repolling.

There's another listener that I can set up, which is if they re-navigate, or the browser reconnects, so navigator goes offline and then online. You get a lot of that functionality built in. Now, in so far that it it's simply the abstraction of fetching data, and those actions, as we talked about before, will go through the remainder of your reducers and stuff along those lines.

It is a really great option if you have a Redux setup. I think that rare query has on the checklist a few more features, totally, but the part that is, for me, as we have to do crazy stuff with our event history and stuff along those lines. The ability to cache the data of very large payloads and immediately navigate and then kick it out from memory and stuff.

And there's a bunch of really powerful features around this that I think work really well inside of this larger toolset. It is definitely a full thing in and of itself. But something that I responsibly wanted to kind of put on the radar, and I need to turn that.

That was, all right, polling every 20 was a little, not even 20 seconds, right, cuz that's milliseconds, was probably a little bit ambitious. So let's turn that off for a second so I can concentrate while I talk to you. No stops, life is good. Is incredibly powerful, cuz that I get the tooling with the rest of my state and kind of can navigate around all those things.

And it will work with any kind of transport layer that you're working through. So I actually need to support multiple ones, both literally talking to a gRPC server running locally, or HTTP if I'm on the cloud version. And being able to do both those things by swapping in just a different endpoints object, right, on the fly, is there's a lot of power that hooks into a larger Redux ecosystem, and I think with a lot of promise there as well.

And you get most of the abstractions. And then all the things that we talked about earlier, about how every action goes through every reducer, right, it becomes like a very easy migration path, right? It becomes the fact that those will then flow through the parts of your application that do have client side state can instantly hook into and listen for those actions.

Cuz you can see them right in the DevTools, and you can hook in, you can kind of do the pieces as you kind of add those functionality progressively. Rather than me like, okay, well now I gotta figure out how to hotwire this into my state management system. I'm not entirely sure it's, like I said before, the right choice if you're completely tabular and you don't have Redux at all.

But I'm gonna assume at this point if you're in the advanced Redux bandwagon this far in that it's a thing that you have and part of your infrastructure and definitely worth it. The API is solely, that create API, some queries, some features and tweaks and knobs that you can turn, right?

But the mutations are simply you'd get put, post, the default base query is just a wrap around fetch that puts in the initial route, yeah?
>> There was also something interesting in the Redux DevTools. So it looks like there is a separate tab for RTK query-
>> Yeah.

>> That is shown on top of this.
>> Right, these are the actual queries.
>> So just pulls stuff from the-
>> Yep.
>> Store.
>> And as you can see, those isError is a successful, what the timings are, you can see those specific. You can do stuff like tagging of the different requests.

You can use invalidation later. And a lot of really interesting parts, you actually see what the also subscriptions and sockets and stuff like that are kinda supported out of the box. And so there's a lot of things. For me, one of the reasons I kinda wanna bring it up is cuz I was 15% into implementing half the stuff myself, and I was not having a good time, [LAUGH] right?

I was doing it, but it was slow going. And I think that there's a set of problems that this solves, or simple stuff like this. But there's a lot of the best practices, the automatic setting of the loading, the fetching, the success, even for very simple use cases.

And like everything else that we've talked about in our time together, does fit in a way that you can progressively move in. You don't have to be like, well, we're rewriting our data fetching layer, right? I think that, for me, one of the very core and interesting parts here is that you can progressively do it for just one piece of the application, because it hooks into the larger infrastructure.

You're not throwing away a lot of code. I think it's for most of us, for our state management layer and our data fetching layer, rewrites are kinda off the table, right? And so ways that you can progressively get these features when you need them, I think is critically important.

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