Check out a free preview of the full State Management in Pure React, v2 course:
The "Refactoring to a Custom Hook" Lesson is part of the full, State Management in Pure React, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Steve refactors code once again, builds a custom hook that fetches data from the url of the API, and explains that it is best practice to use hooks to fetch data instead of components.

Get Unlimited Access Now

Transcript from the "Refactoring to a Custom Hook" Lesson

[00:00:00]
>> But now anyone can use use fetch in the application and I don't think about it. Now, is there probably a use fetch on MPM? I bet there is. All right, there's probably ones that hook into Axios. It's MPM, there's probably 42 of them, right, with varying degrees of maintainability or being maintained.

[00:00:18] But what I would challenge you is four things, even interacting with your own API, there's probably, okay we always get from this API and then we always have to format this data. Don't do that in the components. Where can you take the extractions in your application and make a hook so that you don't have to ever think about it again.

[00:00:34] Right? It could be just a load stat young, use stats, which hits the API, does the formatting. A lot of times I don't know about the rest of y'all, but I work in an API company and they're very wonderful, right? But we use our public API's and our public API's a lot of times are built for developers writing integrations with either Twilio or SendGrid.

[00:00:55] They're not always written for building user interfaces on top of that. So sometimes, I see some nods in the room, right? Sometimes I gotta do a little bit of stitching, right? Yeah, in a perfect world with infinite time, the engineers that I work with would be totally happy to make any damn points that I want.

[00:01:11] But sometimes we're rushing to get a feature done. We got to do some stuff, but we're stitching together multiple API's. And so what I do in those cases is I try to extract that I do not want to keep that component. I don't wanna keep that in my logic anywhere in my component tree.

[00:01:23] I don't wanna write it twice. I wanna put it one place in one hook or higher order component or something along those lines. And then when we get around to fixing it, after we've shipped, and we do the maintenance retractions that we wanna do, I change it in that one place.

[00:01:36] Any time you have to do something squirrely, put it in a box with a nice name. And hide all of your demons deep in your code base right? Do not leave them out everywhere, hide them with well named functions cuz then it's like great. [LAUGH] Leaving it exposed is bad hiding it is good hide your problems.

[00:01:58] That's existential advice as well. All right, let's talk a little bit about you might notice that I'm using promise chaining. Right, and to be clear, I like promise chaining. I actually liked that API I know that you know, with async await and I love async await but for actually making a sync request, I prefer this.

[00:02:20] And we'll kind of see why I prefer it in general, but I also prefer it with use effect. And one of the reasons is, is that you cannot pass an async function directly to use effect cuz they return promises. It's tricky. And so you still need to have an overall function in there, right and then you can have a child async a function that you kick off.

[00:02:45] So if I did wanna refactor this a little bit to use an async function I could do that, you will see why I typically don't, but we'll see why you could, right? But I also just like the syntax better in general, so those are my biases, which I might as well just put out there for you.

[00:03:05] So again, this cannot be an async function right there, we cannot do this, but we can have a regular function that then has a regular function in it. All right, so I could say something like, Or fetchUrl, whatever we wanna call it. Call it fetchUrl, that seems fine.

[00:03:30] And that'll be an async function, where I can do the whole try. And this point we'll say, Const response = await fetch(url). And then from there we'll say, I've got to name it something else, we called it response last time before, we'll say away and we'll call it response.Json.

[00:04:00] Cool and then we'll do self response, Data. If anything blows up, catch the air. I will say set. There is one nice thing I may be able to do here in the try catch block. Which is as before I haven't jacking around with the loading stuff yet and each case cuz with try catch blocks I have finally.

[00:04:29] Whether it went well, whether it went poorly. It went, right. And we're no longer loading. Now my understanding, this is, somebody should validate this before I actually say it out loud, but we're recording. So let's go for it, is that there is finally a method being added to the Promise API in standard JavaScript I don't know when it lands.

[00:04:49] But so the nice part is we get all of this finally stuff. The other thing is we do need to kick off this. So we'd have to say fetch URL because just defining a thing function isn't gonna fetch anything. So let me just comment this one out. So we kinda define an async function, and then we can kick it off and call it.

[00:05:11] I don't like it, but if you have a bunch of async a way code that you're moving, or if there's another context where you need to use an async function, this is how you do it. I choose not to. [LAUGH] Right, but this will do the trick as you can see and so far that everything loaded once again.

[00:05:31] So it's up to you, again could you probably do something fancy with an immediately evoked function? I'm sure that you could but as you can tell that is just not my favorite thing to do in the world. All right, as we mentioned before, we could also kind of use a reducer pattern here as well, right?

[00:05:54] And we could just say, instead of setting all this stuff on and off, we could have a reducer as basically, all right. Are we fetching, did we get a response, did we get an error? And that can then trigger all the flags the way that it needs to be.