Hide the Implementation Details of a Context Provider

Dave Ceddia
InstructorDave Ceddia

Share this video with your friends

Send Tweet
Published 4 years ago
Updated 3 years ago

A single Root component responsible for disparate data like current user, language setting, and theme will become messy and hard to work with. One way to fix this is to move related logic and data into a class, along with a Context Provider to get the data out. In this lesson we’ll group the logic and data for login, and use Context to pass it throughout the app.

Instructor: [00:00] Right now, the root component holds the current user and the functions to update it, and it passes it around with this provider. Let's see how we can centralize the user state functions and the provider all in one place.

[00:12] For that, we're going to use our existing user context file. We'll create a new class here called userProvider. It's going to any render out the provider, which we'll destructure from context. We'll pull that provider and consumer.

[00:26] Inside the provider, we're just going to render this.props.children, so anything inside userProvider will get rendered out here. We'll go back over to root and move some of this stuff over. We'll move over the value that we're passing to the context.

[00:43] Then we'll also move over the functions and the data. Lastly, we want to move over this fakeUser constant. Then we need to change how this context is exported. Instead of doing one default export, we're going to export userProvider and consumer as userConsumer.

[01:05] When we save, we're going to get this error, because of all the places that expect a default export. Let's go update those. We'll start with the root component. Instead of importing userContext, we'll import userProvider and userConsumer. Instead of userContextProvider, we can now use userProvider.

[01:25] Since root doesn't have the current user in state anymore, we also need a userConsumer to get access to that user. We'll use the renderProps pattern to pull out the user from the context object, and then use that user here.

[01:40] That fixes this page, and now, login page is broken. Let's open up login page. We can replace userContext with userConsumer. Down below, instead of userContextConsumer, we'll update this to be userConsumer.

[01:58] Now, we can move onto the messageList file. We'll replace userContext with userConsumer, userContextConsumer with userConsumer. The last problem is in userMenu. We'll open that up and do the same thing here, replacing this with userConsumer and the usage with userConsumer.

[02:21] Now, the app is back to working again, and you can see the context is being used here and here. If we log out, we can log back in. Now, we have this one class that holds all of the concerns for users, and the root component doesn't need to worry about that anymore.

[02:37] At this point, since the class is stateless, we could turn it into a function component by just cutting and pasting the code from render into the function and deleting the class. We could also move this userProvider, and put it at the top level.

[02:55] It's up to you which way you want to write it. This way might be a little bit easier for refactoring later.

Dave Ceddia
Dave Ceddiainstructor
~ 3 years ago

Note: The 'before' code for this lesson is the code from the previous lesson.

Good Knight
Good Knight
~ 3 years ago

@Dave thanks Dave, this literally saved me when instead of trying to fix some side effects, I just used context (well understood by your narrative) and hid the implementation detail - and voila!

Rodrigo Erades
Rodrigo Erades
~ 3 years ago

Hi @Dave, I guess you miss to delete onLogin={this.handleLogin} when you convert it into a function component