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

    Hoist React Component State

    reactReact
    ^0.0.0-experimental-b53ea6ca0

    Hoisting state is a common Refactoring in React.
    State in one component may need to be lifted up to a parent component for coordination with other component state.

    This can be an error-prone refactoring.
    With a good editor, it's best to start with the returned JSX and move out.

    Code

    Code

    Become a Member to view code

    You must be a Pro 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
    orLog In
    Discuss

    Discuss

    Transcript

    Transcript

    Instructor: There is one refactoring that will happen hundreds, if not thousands of times, in any React app, and that is the hoist state refactoring. It's where we take all of the states in a component and we move it higher up in the component tree.

    What this lets us do is coordinate between other states that may be asynchronous. We'll see this in future lessons, but for right now, we just need to do the work of moving this state from this component to a place higher up in the component tree, in this case, our app.

    When I do this refactoring, I like to start by just deleting everything that I don't want in the render function. We'll take that and paste it where it would have been had it existed in this component. I like doing that because it indicates to me via my editor what variables I'm no longer using. In this case, I'm going to pull all of this out, save and move that into my app component.

    I want to take a Pokemon as props. I don't have to move a lot of code around, I'm just going to call this a resource, but you can call this whatever you want. I'll change this to read that resource.

    We have this isPending check and it checks to make sure that the previous resource isn't the same as the current resource. I don't want to have to take two resources to do that. I'm going to move this out as well and move it up.

    IsPending doesn't make a lot of sense name wise in the application context, so I'm going to rename this to PokemonIsPending. We'll take that as a prop named isStale, so we can know whether or not the resource that we received is stale or not. We'll rename that in our component.

    We just need to pass both of those down as props, resource is deferred. Pokemon resource isStale PokemonIsPending. I realized that misnamed this here isState. You're probably yelling at me there.

    Let's look at our component and see what else we missed. We see that initial Pokemon is no longer being used. We know that we moved that, we can delete it, move it over here, save. We see that now these are dulled out as well because they're being called for that initial Pokemon, so we can copy those out as well. Save and import.

    Now that we've moved all the state up, let's jump over to a browser and see how we did. We have two errors, isPending is not used and we're still calling Pokemon here. Let's change those out. This isPending should be PokemonIsPending.

    Here, we need to be reading from that deferredPokemon. DeferredPokemon resource.read, save that and that should clear this up. Click through, see how we did, slow things down, make sure that our slow states are working as well. Looks perfect to me.

    Since we're in our refactoring mood, I thought I would take this delay spinner out and just put in a new file called ui. In this module, we'll need to export it. I won't export it as default because we'll have a bunch of other components in this ui file, but we will need to import React because of our usage of JSX.

    Save that, jump back into our Pokemon detail and import. We'll call it by name by using the named exports from ./ui. Format and save one last time, jump to our browser and we are off to the races.

    Now this Pokemon detail component does what it says, just takes a Pokemon resource and spits out all of the details about it. All of the state involved in fetching, requesting and passing down the Pokemon is all handled at our app level. Now that it's here, we can coordinate it with other app state.