Create a Custom Hook that Creates Resources

Kent C. Dodds
InstructorKent C. Dodds

Share this video with your friends

Send Tweet
Published 4 years ago
Updated 3 years ago

One of the coolest parts of React is the ability to take logic within a component and extract it to a reusable chunk (a custom hook or component). Let's take the logic around our resource to create a custom hook for creating a React Suspense resource.

Instructor: [00:00] One of my favorite parts about React is that we can take logic, put it into a custom hook, and use that logic all over the place. What about all of my components that want a Pokémon resource based on the Pokémon name? What are we going to do with those?

[00:13] Let's go ahead and put all of this in a custom hook, so that we can use it in other components of our application. I'm going to make a function called use Pokémon resource. This is going to take Pokémon name. Here. Let's see. We've got our transition, our Pokémon resource. Let's move those up.

[00:32] Then we're going to need our start transition and our set Pokémon resource. Any time the Pokémon name changes -- let's use an effect for that. use layout effect. -- the reason we're using use layout effect is right now, with the experimental version of concurrent React, use effect doesn't work properly, but use layout effect does.

[00:51] When concurrent mode is stable, use effect will work just fine and I'd recommend that you use that. Then, we'll move our start transition in here, but we don't want to start a transition to create a new resource if the Pokémon name is undefined like when our components first mounted.

[01:04] I'm going to say if not Pokémon name, then we'll just return. We won't do anything there. Then, our use layout effect is going to depend on the Pokémon name. Incidentally and actually it also depends on start transition, but there's another bug with concurrent mode where start transition in the dependency list will cause an infinite loop. We're going to ignore this rule for this line, just for now.

[01:31] I really don't recommend you make a habit out of doing that. When you're working with experimental technology, sometimes you got to do what you got to do. As soon as concurrent mode is stable, you can reliably put start transition in the dependency list and you shouldn't have any trouble.

[01:45] Let's go ahead and update new Pokémon name to be Pokémon name. There are only two things left that we're not using in here and those indecently are the things that our users are going to need. Let's return Pokémon resource and is pending.

[02:01] We're the rulers of our hook, so I'm returning an array here, but you could return an object or whatever it is that you want to return from your particular API. Now we have our use Pokémon resource, so I'm going to say use Pokémon resource, we'll pass the Pokémon name and we'll get back our Pokémon resource and that is pending.

[02:19] Anytime the Pokémon name changes, that will trigger a re-render under a transition and is pending will be set to true. Our Pokémon resource will be whatever new resource we created for that Pokémon name. Then we can render this out based on that Pokémon resource. That's all it takes. If we save this and try out our app, everything is working just as it was before.

[02:42] In review, what we did here was, we just took a couple of the things here that were dealing with the resource specifically. We extracted it out to a use Pokémon resource hook that accepts the Pokémon name. Whenever that Pokémon name changes, we start a transition to update our Pokémon resource.

[02:59] We're still using this get Pokémon resource function, which is creating our Pokémon resource. That's what we set the Pokémon resource to. That triggers a re-render so that the component can use the Pokémon resource and render the Pokémon info, which will suspend until that Pokémon resource resolves, which will trigger another re-render and render out the resolve data from the Pokémon resource.

Viktor Soroka
Viktor Soroka
~ 4 years ago

I did not get why the dependency over startTransition in the useLayoutEffect. Could you please clarify the need for this.