Check out a free preview of the full Complete Intro to React, v7 course:
The "Context for Theming" Lesson is part of the full, Complete Intro to React, v7 course featured in this preview video. Here's what you'd learn in this lesson:

Brian demonstrates using context to set a button theme based on the global state. This process can also give an application light and dark mode.

Get Unlimited Access Now

Transcript from the "Context for Theming" Lesson

[00:00:00]
>> Once you create a new file, and I want you to call this ThemeContext.js. We're gonna import, createContext from react, we're gonna make a thing called ThemeContext with createContext. And then like a hook, you give it a default value. So this could be something like brown. However, the way that we're going to store this, we're actually gonna use a hook.

[00:00:39] So we're gonna use useState to represent our ThemeContext. So we actually want our default value to be what a hook looks like. Sorry, specifically a useState hook. And if you remember, I'll just show you here like const theme setTheme. Equals useState darkblue or whatever, right. This is what a hook looks like, right.

[00:01:13] So we needed to mimic what this is. Honestly, you can actually just do this and it would be fine. But, again, we're gonna get into TypeScript later. And if you give it what the default value is, then it knows the type of it. And it can use that throughout your entire application.

[00:01:32] So we're gonna give it something that looks like this. So we're gonna give it our default color which is going to be green or whatever color you wanna put there. You can put whatever your favorite hex color is. I remember from Chris Coyier from CSS tricks his is fog dog.

[00:01:55] F06d06, and I believe that's orange. Anyway, whatever you want. I'm gonna put green. It doesn't matter, cuz it just matters that it's a string or something like that. And then we just wanted an empty function that does nothing. Cuz if someone calls this and it's not actually a hook we just wanted to invoke a function that does nothing.

[00:02:19] So this is just an empty function, right. Okay, and then we're going to export default ThemeContext. So I know this is a little strange, but at the end of the day, we're just mimicking a useState hook. That's the TLDR. And this will actually never be passed around. The only reason that this would actually be used, is if you ever used the context without setting the context.

[00:02:52] Which you would never do, just for the record. I guess the only time you might do it in testing but even then that'd be a really strange way of doing it. Yeah, question.
>> I was just gonna say I appreciate you explaining this because I feel like I've seen this in tutorials a bunch of times.

[00:03:08] I've always been like, why are we putting something here and what happens with it.
>> Yeah, our app would totally work if you just did this. You don't have to put anything in there. But for types, and technically it would get used if you didn't have a parent provider of context, but I'll explain that in a second.

[00:03:29] But it is good, specifically for types. Even if you're not using TypeScript VS Code can read the types from TypeScript. Cuz it's actually TypeScript running in VS Code to tell you what kind of value it expects there. So you still get the benefits of TypeScript even if you're not writing TypeScript.

[00:03:45] So that's why I have you do that as well. Okay so now we have the ability to use this context provider and context consumer in our application. And I'll show you both how you do both of those. So I'll head back first to App.js We're going to import ThemeContext from ThemeContext.

[00:04:13] We're going to create a hook here called the theme = useState from react. So you have to import that up here as well, cuz we didn't have that already. Make this the actual default color that you wanna use here. So I used darkblue which is a valid CSS color, right.

[00:04:34] But you can put whatever valid CSS color you wanna put there. Okay, and notice that I'm not destructuring it here, which is a bit strange. But that's because I'm going to pass it into my context. Okay, and then here, inside the StrictMode, I'm gonna put ThemeContext, value equals theme.

[00:04:59] Sorry, ThemeContext.Provider rather, value equals theme. Okay. Now why do I have this component? Well anywhere inside of this component, now that ThemeContext is available. So any component all the way down the tree. So all the way down to the lowest pet component in there can read off of this context.

[00:05:33] If I had something other component here and notice that it is outside of ThemeContext. Everything in here could not read from the theme, right. Now you can get crazy about this, and you can say it seems ThemeContext provider. You can actually use to two different theme contexts and you can have a theme2 here, which is green.

[00:06:02] And value equals theme2, so you actually use the same code twice. And have different, and so this one if I ever called read from the consumer here, it would get green, right. And if I called it from within here, I would get blue. I've never had a use case for this.

[00:06:25] You can actually get even stranger than this. I can have a third one here. And have a value equals, let's just get rid of this one for now, well, actually forever. [LAUGH] ThemeContext equals theme2. Sorry, this would have to be the ThemeContext.Provider rather .Provider. So now I have nested ones, right.

[00:06:59] So let's say inside of here I had other component, okay. Now inside of other component let's say I read from the context. Which theme would I get? I would get theme2, right, cuz actually it gets the closest one. So this one could have a different one set than everything out over here.

[00:07:22] Now, I'm showing you all this again, I've never had a use case for this. This sounds wildly complex for reasons that are unknown to me that you would want to do this. But I'm just showing you that it is possible. And that's why they have it built into a component so that these kind of patterns are possible.

[00:07:40] My plea to you is never do that [LAUGH]. If you can avoid it at all, I'm sure there's gonna be some great reason for some niche use cases. It's gonna be amazing and you're gonna be so happy they did it. And probably upset all your coworkers, that's fine.

[00:07:56] Okay, so here we are. We've created this, we have one theme, we're doing no more than one theme, please do not. And now everything inside of here can read from the ThemeContext. Question so far about that, we're not doing anything with the context now. Now it's just available but we're not reading from it.

[00:08:25] Cool. So let's head into ThemeContext, we're gonna go into search params. Using context with hooks is awesome and very easy. You just pull in, useContext, And then here at the top we're just gonna say const theme equals useContext ThemeContext. So we pulled in ThemeContext up here, we pulled in the useContext hook from react, and we just give useContext ThemeContext.

[00:09:24] And all of a sudden we can just start reading off of the context. It's very easy. Now, keep in mind, there is setTheme here, we're just not using it, right. And so we don't have to pull it off if we're not gonna use it. Okay, and now to make our button very beautiful.

[00:09:44] Button style equals, so this is just like CSS style, right. And you can just give it an object of styles to apply, so I'm gonna say background color theme. Cool, and now, if you go over here, notice the button is now blue, Or if you go back to your app.

[00:10:22] Whatever you put here is now going to be the color of this button. So pink, there you go, turns pink. Yeah, so that is the most pleasant use case of reading out in a hook, the context.
>> Could you please show the button coding.
>> Yep that there.

[00:10:54]
>> I see, thank you.
>> Yeah so some of that might be a little confusing. There's two sets of curly braces here.
>> I was thinking about that the first set is to do that JavaScript thing of we're-
>> Putting code here.
>> Putting code here and the second one is specifically that's an object.

[00:11:12]
>> Yep, I appreciate that VS Code colors now in two different colors, it didn't use to do that. But semantically even though that you have two curly braces next to each other they mean different things, right. This is an object and the outside one is letting JSX know that it's an expression Okay.

[00:11:41] So, let's go into details because we wanna make it so this button is the same. Right, so that this one also reads from the context. Now, let me show you how I would do this, if I was lazy, which I am. I am already using hooks here, I would definitely just say const theme.

[00:12:03] And I would just use the context hook here and then pass it in. Why wouldn't you, that's super easy to do, right. But I'm gonna show you how to do it the hard way. So, import ThemeContext from ThemeContext. Then I want you to come down here to the button.

[00:12:25] And the way we're gonna do this is we're gonna do ThemeContext.Consumer. And then we're gonna say, this gets invoked with a function. And then we're going to do a function here, that's gonna read from that theme. Now inside this theme, we wanna pull out the theme here, right.

[00:12:53] Cuz this is destructuring that to get the theme out of it. And now inside of this context we can say style equals backgroundColor theme And we can put Adopt name. So that [LAUGH] is how you read out of context in the class component. So this function gets invoked by react with the theme context that we asked for.

[00:13:49] That's what ThemeContext.Consumer does for you. Pretty unreadable, isn't it? Yeah I'm not a fan. Which is why I'd say just say const theme equals useContext(ThemeContext), and then just pass it in here, right. Theme equals theme, bam damn now, it's this dot props out theme, right. But we'll leave it, I think it's good for you to know how to do it.

[00:14:36] There might be some reason why you might not want to. This is how it used to be done before hooks were a thing. This used to be a really common pattern in React. Of having a parent component and then a function that would get invoked inside of it.

[00:14:56] With some sort of passed in detail, it was annoying. Be grateful that you have hooks now which are a lot easier to deal with that kind of stuff yeah questions.
>> Are you gonna implement the ability to change this or what would be the best way to-
>> The next thing [CROSSTALK] I'll come and talk about that next, yeah.

[00:15:14] Good question, let's go make sure that actually you can see here now the button is blue.