1. 23
    Provide Suspensified Data to React Components with Context and useContext
    5m 52s

Provide Suspensified Data to React Components with Context and useContext

Michael Chan
InstructorMichael Chan
Share this video with your friends

Social Share Links

Send Tweet
Published 4 years ago
Updated 3 years ago

Proper Suspense code can mean a lot of functions wrapped in other functions.
Because these function are composed with Hooks, modules can't help us hide the implementation details.
But Context can!

Let's explore how Context Providers, Consumers, and the useContext Hook can integrate with Suspense to mask wordy useTransition-wrapped API calls.

Instructor: [0:00] Let's explore and create a Context.Provider for our resource reading components. For me, context always starts in a new file that I can import wherever I need it.

[0:12] Here, I'll start a new file called pokemon.js. As this application grows, I'll put a lot of named exports in here, but we'll start with context. Import React from 'react'. We'll need that for creating context, and export const PokemonContext, which we'll create with React.createContext.

[0:39] Back to our app, where we will use it for the first time. Let's import it at the top. Now, it's a named export, so we need to use these curly braces, PokemonContext from Pokemon.

[0:56] In this, Pokemon context is both a provider and a consumer. Let's use the provider to wrap this Pokemon detail component, which we already know is consuming a Pokemon resource. PokemonContext.provider, we'll give it as a value an object that we haven't created yet, PokemonState. Now, wrap our PokemonDetail.

[1:21] The goal is to update PokemonDetail in such a way that it doesn't require these props. Let's move up a few lines and create our PokemonState. What PokemonState = new object, change this to Pokemon, update the syntax but leave the assignment the same at the bottom for isStale.

[1:49] Now we have this little object that we're using to provide as context to PokemonDetail. Next, we just need to update PokemonDetail. At the top, we import our context again as a named export, Pokemon context from ./Pokemon. We can delete these props. We won't need them anymore.

[2:14] We'll use React.useContext, the hook to capture context from Pokemon context. We will assign that to a couple of local variables. We'll reassign Pokemon to resource since we already have that here and take isStale as it is.

[2:36] Our app's complaining about this Pokemon value. Let's refresh it to make sure that's valid. Now it looks like our context is invalid, so let's go back and see what we're doing wrong. Looks like I just need to save this app file. There you have it, PokemonDetail is now using context to get its value. I'd like to set values as well. What does that look like? How can we set a Pokemon?

[3:05] Let's a find a function where we're doing it already. Here in PokemonCollection for renderItem, we are setting Pokemon anytime one of these buttons is clicked. Let's comment this out so that we can have access to it later and get all the context in place. We'll call a function called setPokemon, and we'll use the same value as before, PokemonID.

[3:31] We need to wrap this in a PokemonContext.Consumer if we want to get the callback out of it. It uses a render prop API that we can pass a function to. That function will have access to the state that we gave it, including the setPokemon function, which is all we need here.

[3:56] Take that and wrap it on over to the bottom, and we're good to go on this side. We just need to move this function up into our PokemonState object, and format.

[4:08] We have one last problem. Our PokemonContext.Provider we initially kept very tight, but we're going to have to move it up in the tree if we wanted to include everything that we have, all the way down to this setPokemon down here.

[4:25] Let's keep our fingers crossed, see how we did. "Pokemon is undefined on line 33." Of course, we need to take an ID and use that instead. Format, save, and click a few buttons. We did it.

[4:46] Something that I like about this is that we can create a setPokemon function that has everything that we need to make these transitions nice and smooth. Additionally, components that read resources, like this Pokemon.Detail component, aren't truly agnostic. You can't just take any Pokemon and then render it. They are always going to read from a resource.

[5:10] If they're already coupled to the application implementation, why not also read them from context? Of course, an issue that we have here is that we're recreating this state object every render. If it gets really big and unruly, maybe you might see some performance issues.

[5:27] As for right now, with the application that we have, I really like it. It hides all of the Suspensey details and lets us call functions like setPokemon instead of startTransition arrow function setPokemonResource Suspensify fetchPokemon with ID. Your mileage may vary, but as far as working goes, it definitely works.

egghead
egghead
~ 2 minutes ago

Member comments are a way for members to communicate, interact, and ask questions about a lesson.

The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on egghead.io

Be on-Topic

Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at support@egghead.io.

Avoid meta-discussion

  • This was great!
  • This was horrible!
  • I didn't like this because it didn't match my skill level.
  • +1 It will likely be deleted as spam.

Code Problems?

Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context

Details and Context

Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!

Markdown supported.
Become a member to join the discussionEnroll Today