Join egghead, unlock knowledge.

Want more egghead?

This lesson is for members. Join us? Get access to all 3,000+ tutorials + a community with expert developers around the world.

Unlock This Lesson
1×
Become a member
to unlock all features

Level Up!

Access all courses & lessons on egghead today and lock-in your price for life.

Autoplay

    Extract Generic React Hook Code into Custom React Hooks

    Kent C. DoddsKent C. Dodds
    reactReact
    ^16.7.0-alpha

    Because hooks code is regular JavaScript, extracting it to its own function is trivial and enables code sharing in a really nice way. It also allows us to encapsulate and separate concerns really cleanly. Custom hooks also compose really nicely together to build more complex hooks out of more primitive ones. Let's do this by creating a useSetState and useSafeSetState custom hook.

    If you would like a more comprehensive useSetState hook, give use-legacy-state a try.

    Code

    Code

    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson
    Discuss

    Discuss

    Transcript

    Transcript

    Instructor: One of the cool things about React hooks is that it's really just JavaScript. This is just some JavaScript that we're running right here. This is some JavaScript. We're just calling a couple functions, and we can extract this into our own custom functions.

    I'm going to take this logic right here, and I'm going to make a useSetState custom hook. We'll say useSetState, and then we'll just move this right up here. Then we can return state and setState. Then we can actually pull in our state and setState from useSetState.

    That was just a pure refactor, not really actually changing any behavior at all, just moving code around. Now, we want to make this actually generically useful. Having this loading fetching data and error state in here as the initialize state doesn't really make sense in the context of other components.

    I'm going to actually take this out, and we'll call this initialState. Then we'll put in initialState here. Then we'll pass that initial state to our call to useSetState. That's just another refactor, just moving things around.

    Now, we can use this useSetState function anywhere, and we can get an experience in refactoring other components in a way that's similar to the way setState works in React. Again, we're not supporting the updater function API from setState or the callback as the second argument to setState.

    This is covering our use cases here, and we could add support for those later, or we could actually use the NPM module, use-legacy-set-state, which is basically this.

    The next thing that I want to do is, this also could be usefully generic. I'm going to make a new hook here that's called useSafeSetState. Here, it's going to take some initial state as well. What we're going to do is I'm actually going to reuse this useSetState in here.

    I'm going to get my state and setState. We'll call useSetState with initial state. Then I'm going to take this mounted ref all the way down to the safeSetState down here. We'll just put it right there. From here, we'll return state and safeSetState.

    Then we can actually just use safeSetState right here. This can be safeSetState. Cool. Now, we'll just update that setState call there to use safeSetState instead, which will work just fine.

    Now, we've been able to extract some generic code from our query component into these little custom hooks that encapsulate some specific use cases, and are even composed together to form a really nice, cohesive useSafeSetState hook.

    Really, the way that we did this was we just moved some code around, made some functions, and then called those functions instead of the React hooks directly in our query. Now, if we save this, and go here, just to make sure that things are working, it is still working.