Transcript from the "useContext" Lesson
>> So let's talk about context. So this next one here, the first level second, this one here on the right side, this is context. So, you can see here, I have a very professional username here Bob Olsen. That's Bob Robertson example.com. This is an example object that we're creating here.
[00:00:29] So let's talk about what context is and what context solves. And we go over this a decent amount in the complete intro to react. So if you want more intro to context, there's a good section on that there. But there is a kinda problem in react because data flows very explicit in react.
[00:00:49] You have a component that lives in the top component like your app.js overall arching application. But you'll have components five layers down that you need to read. Then from that component, right? So say for example, here and this component has something here at first level. And I needed to read it from down here.
[00:01:13] In this particular level, right? If this was if I was not using context, I'd have to pass that piece of data parent to child parent to child parent to child all the way down, right? So you can see here I have my level, one component here. Which is like the context component, right?
[00:01:34] That then renders a level two here, right? Then renders a level three, that renders a level four, that renders a level five, right? If I wanted to pass the user state down here to level two. I'd have to do this bit by bit by saying user state equals user state.
[00:02:00] It and then I'd have to do this on every single one of them right? I'd have to do it here. Then I'd have to do it here. And this will come in from props, right props that user state. Again and so on and so forth. And I'd have to prop drill that's the name of that problem.
[00:02:21] In the react community. And we used to have to have to do this all the time, right? So this component like level two and level three, they don't care at all about user state cuz they're not reading reading from it, they're not rendering it. All they're doing is they're just passing it from the parent to the child blindly.
[00:02:40] This is a problem on several levels. One, it just makes your code more complicated than it needs to be, right. And then the other thing is like if I go to test level two or level three. I have to like pass in these arbitrary things because it expects them even though it's not using them.
[00:02:53] Or maybe like level three was like more reusable and. But it doesn't always need that user state. I still have to would have to pass in that user state because they're expected, right? So enter context. You can think of context as basically like a wormhole in your application that you can like dump stuff in one side.
[00:03:15] And it's gonna come out the other side right? So here in this user context provider, I'm dumping in the value of user state, which is this hook from here, right. It does not have to be a hook, right. It could be anything, right. It can be a string, it can be an object, it can be anything, right.
[00:03:32] I'm just using the hook here because it's convenient, right. And then here down at the bottom inside of this, I'm using the US context here to pull out that hook, right? So I have something I'm creating here, level one. And then I'm reading it down here at level five.
[00:03:49] That's what context does for you. So I'm gonna now that I've taught you this like magic way to circumvent the one way data flow of react, please use it very sparingly. Because now I have this very I haven't have level five and level one that are kinda tied together.
[00:04:05] But it's not explicit, right? It's hard to reason about that. If I'm reading my code, especially like if I'm hearing like level four or level three. I'm like wondering how the hell does it get? Does this child component get access to that information, right? Because but typically with react you'd see that prop drilling.
[00:04:23] So I'm kinda talking out of both sides of my mouth here of like hey here's this really cool way of doing it never do it that way right. To me what's important here. And the reason why I chose like a user here is you want. Things that go into context be application level state.
[00:04:40] And when I say application level state, things like users, right? So if I'm logged into my user account, I have to read and write to that user account from all over my application. So the example that I used in the intro is like your Netflix user account. I have to be able to set my settings which reads from the user account, I have to be able to see my streaming preferences.
[00:05:02] Which comes from the user account have to be able to upgrade my plan or downgrade my plan or cancel my plan. All those things read from the user accounts. So that is universal application state. The user makes sense to my entire application soon. That is a wonderful candidate for something to put into context.
[00:05:18] But I don't know a counter or something, you're just lazing you don't wanna pass around. That's not a great candidate to put into context. Okay and then the last thing I was gonna show you here is because I'm using a hook. You can update it from level five down here right so I have a button here that if I click.
[00:05:39] Notice here that I can increment it down here, this number is incrementing here. Despite the fact that that's still state is being stored up here. In level one, right. Despite the fact that the it's being called down here in level five. So you can do things that where you can actually update the parent as well from the child held.
[00:06:02] But again, it's a very implicit relationship that those things have their implicit code is the worst code. Because it just makes it hard to follow and debug. If there was a bug here on James the Jameson the it was like skipping to be every two or something like that.
[00:06:20] It's kinda hard to reason about it. At that point, what's going wrong. Because we have this context, worm hole in the middle of it. And we don't know which side has the problem. It just makes it harder to debug. As you can tell, I basically like my entire theory around programming.
[00:06:42] Because I know I'm gonna make a lot of mistakes. How can I recover from those mistakes the fastest? Yeah, that's sad. [LAUGH] Anyway, anyone have any questions about context or use context? I guess I didn't really touch on the hook very much. If it's the use context hook is like one of the nicest to use.
[00:07:05] All you have to do is give it the context, which is this create context thing here. And then you can just pull things out of context. Pull things out of context. Nice, anyway. Yes.
>> How do you avoid the urge to not use context everywhere? Experience I think is the answer to that question.
[00:07:25] I've had enough problems of where is this coming from also I used to use the old react context API which was a mess, right? So I think that react context just sends chills down my spine so that helps a lot to me. I don't use it everywhere because most things are not application level states, right?
[00:07:46] Most things are like view state, right? Sure, am I in dark mode or light mode, actually, that would be a good candidate but in context as well. Because that would apply your entire app. The like is this button on or off right. That's definitely like view level state.
[00:07:59] Most things in your application you're gonna end up being view level state. If a user is filling out a form right I don't need to store that in the for the entire application to read from it just stays there. So, yeah I recognize that as soon as I introduce context I'm introducing something that can be really hard to debug later.
[00:08:19] And that keeps me from putting everything in there.
>> Can use context be scoped if I create a context and a component is available to the whole app or only in the component children.
>> Good question. Which I didn't actually cover super well here. So create context here.
[00:08:38] This gives you like this user context object. There's two things that come on this. One of them is the provider. So you can see here I'm wrapping this entire component in the user context provider. Everything inside of this provider can then access that context. Nothing outside of that context, can access the data inside of that context.
[00:09:00] So you actually you are actually scoping it to that part of the app. I can actually have two separate, context components here. That have different contexts right. You can also nest it right so I can actually put it. Another provider here in fact let's just do it it might be fun.
[00:09:20] User context provider and value equals use state I guess I need the whole object don't I. User context provider, that one. So you can see here now it's actually reading from the closer one here Sam Sanderson instead of James Jamison. Because this one's closer to it right. So you can actually have like sub scopes.
[00:10:28] So I really don't want you to do this because this would be even like we're talking about making things hard to debug. You could definitely see a situation where like I found where the context is coming from. And then you don't realize that there's a context in between the two of them.
[00:10:43] I don't really know when you would have a good reason to do this, but I'm just letting you know it's possible. But please don't. Don't make me regret showing you that. If you really like Redux but you don't wanna pull in the whole Redux library. And we'll talk about Redux later.
[00:11:02] If you use the two hooks together, use context and use reducer. You kinda get like most of what Redux is. Fun fact.
>> How do you usually handle more than one different types of objects in a context?
>> How do you handle more than one type of object inside of context?
[00:11:25] You just put make it an object, right? So you can see here, I have this object here which is a user. If I had, well there's two ways of going about this. You can either have two different contexts, right? So I could create a user context and a preferences context, right?
[00:11:40] Or I could have one talk context where I have A top level. I have an object and inside of the object there is the preferences part of it. And there is the user part of it, right? Basically treating it like a Redux store at that point. And you might be asked me which one is preferable and I'm gonna say that's super contextual to what you're doing unintended.
[00:12:01] [LAUGH] There's not a right or wrong answer there. You can make cases for both of them. And I don't think that I have strong feelings either way. It would be annoying if I looked at an application and there was like 19 of these contexts providers wrapping things. So there's definitely a layer of too little granularity.
[00:12:24] But if you have two things that are totally unalike in the same context I also take a little bit of offense at that as well. So somewhere in the middle I guess is my answer.