This course has been updated! We now recommend you take the Complete Intro to React, v8 course.

Check out a free preview of the full Complete Intro to React, v7 course:
The "Custom Hooks" Lesson is part of the full, Complete Intro to React, v7 course featured in this preview video. Here's what you'd learn in this lesson:

Brian demonstrates how to extract logic out of a component to allow a hook to be shared across components.

Get Unlimited Access Now

Transcript from the "Custom Hooks" Lesson

>> We've used set state, or sorry, useState, and we've used useEffect. One of the cool thing that you can do with React is you can make your own hook. Now why would you wanna make your own hook? It's a dumb question, you don't, I'm just kidding sometimes you do, but not frequently.

[00:00:21] Well, I guess that's kinda debatable depending on who you talk to. There's some people that say, I use everything as a custom hook and I use no useState in my industry. People are wrong don't listen to them. Basically, if you find yourself doing like a song and dance of several hooks in a row, and that's also generally applicable to another component, that's a good candidate for something to be a custom hook, right?

[00:00:46] So a good example of that is like, maybe you have, this is a good example. Someone gives you a city and then you use that city to call and get like a zip code, right? You can see that kinda workflow happening. If you do that a lot, you could get like a use zip code hook that you just provided a location and it gives you back a zip code, right?

[00:01:06] So that would be a really good candidate of like a workflow that would work really well into a custom hook. In our particular case, we're gonna make one called useBreedList because we can get a breed list back from our API if we give it an animal, all right?

[00:01:20] If we're doing a pet adoption app that can be useful in several places. So instead of putting all that logic here, we're gonna make our own hook called useBreedList. So go ahead with me create a new file called useBreedList.js. And we're going to import useState, useEffect from React.

[00:01:50] Let me make a local cache. And we're gonna make this, so that if you go from you call, breed lists with dog and it goes and gets you poodle and Chihuahua and the called cat and it gets you back, Tabby and Siamese. If you go back to dog, we wanna make it so that it doesn't go back to the API it just gives you the local cache.

[00:02:10] Now we're just gonna do an object here, but you should use something like local storage for this, right? We're just simplifying everything by just making it an object here, Okay? Export default function, UseBreedList, Okay? And then here we're gonna say const breedList and setBreedList=, you may have guessed useState, you'd be correct, empty array.

[00:02:48] And const status, we're not gonna be using the status in this particular course or anything like that. But I'm just gonna show you how I would have built this if I was gonna use this in several places. What's useful about this is now we can check in our components, is this pending, is there an error?

[00:03:06] Is this working? It'll be like a status of what the breedList is in at the moment. So then you could show like loading spinners and stuff like that. So, then this is gonna be a useState we're going make it like an enumerated type, right? An enumerated type is basically like this, can only be like a subset of types.

[00:03:28] This can either be either unloaded, or pending, or loaded, that's it. So it's gonna start out in an unloaded state, Okay? First thing here we're gonna use effect, this is gonna be a function and we're gonna say if no animal, Then setBreedList to be empty. So if someone asks for a BreedList for empty string animal, you just give them, there are no breeds for no animals.

[00:04:04] You get nothing. Else if local cache has an entry for this, Then give them that, Else, request breedList, With, Okay? We're just gonna put this inside of our effect here. So we're gonna make an async function requestBreedList Takes no parameters. First thing if you call setBrainList, we're gonna send the breedList to be empty.

[00:05:05] So for example, if I go from dog to cat, immediately I wanna stop providing breeds, because now I have no breeds that are gonna be accurate, right? Basically, you don't wanna get into like some sort of like halfway state where you have dogs that are Siamese, right? And that's the point here.

[00:05:24] SetStatus, to be loading, And then we're gonna say, const res=await. I need to make the fetch first, res=await, res await fetch.' and animal=animal. Again, remember those are backticks because this is a template string, Cool, that'll get there. const json = await res.json. So we're gonna store this in our local cache = json.breeds or nothing.

[00:06:33] So if you go out and try and get horses for example. And the API doesn't support that. It's just gonna give you back an empty ArrayList. That's what the or does here. SetBreedList, LocalCache animal. This is a habit of mine by the word animal come from that just comes from, sorry up here useBreedList here line five, you need to take in a parameter of animal that's important.

[00:07:11] That's like, how are we giving like empty strings to useState. This is that string coming in from wherever the hook has been called. Cool.
>> Why 23 and the API call are we doing /breeds and that /pets breeds=? Great.
>> So this is just the name of the API that I made for you.

>> In search-
>> So-
>> Columns of /pets.
>> Right, which is a different API.
>> Okay got you.
>> Yeah. Two different API's. Good question. But prove my point here. You call with dog you'll get all these very different APIs back, if you call with pets, you will get specific pets, so this will give you all dogs.

[00:08:04] Good question. Okay, Someone might ask me, hey, why are you using the localCache instead of just doing json.breeds kinda just force a habit I suppose. I mean, they end up being the same thing cuz you're setting them to be equivalent to each other. And then setStatus, I guess, technically the cells a race condition.

[00:08:39] But as you requested two animals in quick succession, one where the first request was slower than the second, probably around the second closer than the first, they would come back. I don't know, anyway, you there's probably a race condition there. I don't know some figured out and fix it for me.

[00:08:55] So what open source software is for? Like halfway kidding on that. [LAUGH] Okay, so now we have this great little useEffect function. This one is gonna say, hey, you have dependencies you haven't declared yet, which is true, we do. We're going to set them here and we're dependent on animal, Okay?

[00:09:31] So basically what's cool about this now is, this is now keeping track of like whenever animal changes, we request it, we don't have to like handle any of that logic ourselves React by giving animal here, now this is React promises. React is gonna know okay, animal change time I gotta recall this one, right?

[00:09:53] And it keeps track of all those dependencies for you. I'm gonna say return breedList and status. So I'm just adhering to their normal array type things. Since all hooks use this I just kind of keep with the tradition, but that's why I'm doing that. There's no reason you have to do it this way.

[00:10:16] It's just the way that I chose to do it here. And the other thing I'll tell you here, we are providing the status back to the user so they can see that it's either loading, loaded or unloaded. We're not gonna use it throughout the rest of the course but it's just like a good idea, right?

[00:10:32] Okay. And now, this breed will be available to us whenever we use this hook.