Building out the Current User Provider
In the last guide, we built out our initial CurrentUserContext. Whenever you're using a context or the context API in React, you're also always going to be build what is called a provider.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

Now, the context is more of just a interface and it's some boilerplate code that you need to make the context API work but with the real logic, all the business logic is going to go into the provider and that's what we're going to build out in this guide.

So let's open up our provider file. Right now it's completely empty. And let's start adding the code that is needed here. So I'm going to start off by importing React. So I'm just going to say import React from react and then also, I'm going to bring in a few other elements here. So I need to use useState and useEffect and I'm going to walk through what these hooks do.

CurrentUserProvider.tsx

import React, { useState, useEffect } from "react";

We've already worked with useState quite a bit but we're going to walk through how to use the useEffect hook as well. And then from there, later on, we're going to import the secure token. We're not going to do that for this one right now. For right now, we're just going to create the provider.

Now, the first thing that we're going to do, like any of our other components that take in a prop, is we're going to build out an interface. So I'm going to say interface and I'm just going to call this ICurrentUserProviderProps and for this interface, it's just going to take one prop and as you're going to see, this is going to work very similar to a layout prop. All it does is it takes in children. So we're not going to actually be passing any props directly inside of this component, except for any of the code or any parts of the application that are going to slide inside and so for that case, we're just going to say children and any.

CurrentUserProvider.tsx

interface ICurrentUserProviderProps {
  children: any;
}

Now let's build out the component itself. So I'm going to say actually export default and then we're not going to name this, we're going to follow that kind of convention where we're just going to say export default. We don't have to give it a name because since we're only exporting one item, any other part of the application that calls this is going to be able to call it whatever it wants. So export default and then let's just pass in props with our interface of ICurrentUserProviderProps and this is going to be a fat arrow function and inside of it, let's first start off by just returning a call to that context so the way that that works is we're going to say we want to use the CurrentUserContext and so you have to import that and if you have the same utility.

I forget if I've shown you yet the utility I use for auto imports like that but it's this one right here. Auto Import and that makes it so that if you just start typing in one of the components and you hit Tab, it'll actually bring that file in. So that, as you can see, it brought in that context just like that and then inside of this context, we're going to call props.children and we have to make one other change. As you can see, we have some red underline here. It says JSX element type CurrentUserContext does not have any construct or call signatures. So what we need to do there is we need to say Context dot and then we have some helpers. So we have the ability to create a Consumer, a Provider or a displayName. We want to use a Provider and then we also have to finish it off and say .Provider here. Because the context by itself, like I said, doesn't really do anything. It's just more of an interface. It allows us to reach in and work with the context API.

CurrentUserProvider.tsx

export default (props: ICurrentUserProviderProps) => {
  return (
    <CurrentUserContext.Provider>
      {props.children}
    </CurrentUserContext.Provider>
  );
};

And if you've not worked with the Context API very much, much of this may seem really confusing. Do not let that bother you. I think one of the best ways, at least for me, for learning how this works is by building it out and seeing the final effect, to see the behavior that this code generates and then from there, then it makes a lot more sense.

So I'm going to say CurrentUserContext.Provider and we have to pass in a value. That's why we're still getting some red marks here. So the value we're going to be passing in is some state so let's actually create some of that state. So I'm going to say const currentUser and then setCurrentuser and that's going to be equal to useState and to start this off, we're just going to start it off and say that there is no current user and so for right now, that's all that we need to do so I'll say value equals and then what I want to do is create an object set of values here and so let's actually create the state value.

So I'm going to create a variable here called const and just call it stateValues equals an object and that's going to be currentUser and then setCurrentUser. And then inside of value, then we can say stateValues. And now you can see all of the red is all gone which means that this is all set up properly.

CurrentUserProvider.tsx

export default (props: ICurrentUserProviderProps) => {
  const [currentUser, setCurrentUser] = useState(null});

  const stateValues = {
    currentUser,
    setCurrentUser
  };

  return (
    <CurrentUserContext.Provider value={stateValues}>
      {props.children}
    </CurrentUserContext.Provider>
  );
};

Let's walk through exactly what's happening here. Okay because I know this can be confusing if you haven't spent a lot of time building out or working with the context API. So just to start from the beginning, we're importing React and a few hooks. We're going to be using state so this is going to be just like we've used state before in the rest of the application. This just gives us the ability to hold some state, hold some data or some persistence in this component. useEffect, we are not calling it, we are going to call it in not too long and that's going to be the trigger we use and we're going to say whenever this component loads up, I want you to start this process, whatever that many be.

Then next we're importing the context. That's just that boilerplate code, it's what allows us to connect into React's type of context API. Then we're creating our interface. We're saying that children are going to be the only thing that are going to be used or passed in as a prop. We're creating a base state for users and then we're creating a variable that holds both the ability to grab the currentUser and also to set the currentUser and then we're passing that in as the value.

Now, to test this out, let's just create kind of a dummy user. Later on obviously we're going to be using the real users coming in but for right now, let's just create a dummy user here at base state. So I'm going to create an object inside a current user and let's just say that this object has an ID of 123 and an email of hey@you.com. So we're just passing in a dummy object. Our real users are going to have more data points than this. So I'm going to hit Save here and so whenever this component loads up, it's going to actually have the currentUser set to these values.

CurrentUserProvider.tsx

  const [currentUser, setCurrentUser] = useState({
    id: 123,
    email: "hey@you.com"
  });

So let's now go into our App.tsx file and now what we're going to do is we're going to import and then wrap up our entire application or our AppContainer with this currentUser provider. This is where hopefully it's going to start to make sense what we're doing here. Remember, the goal of working with the context API is to be able to wrap up a full set of components and in this case, we're wrapping the entire application and we're wrapping it up with this provider so that all of the other components inside the application So that means when we're creating a post. If we need some data for that user, from that user, then we can reach into that current user provider, grab those values and then use them however we need to.

If we were not using the context API, and say we had a chain and to help, it kinda helps to have a visual here. So say you had a set of screens and components and you wanted to pass the current user as a prop, you could very well have to pass that current user into one component only to pass it into another one only to pass it down to 10 components down the chain. That is not a really good way to write your code. Instead, when we're using a provider, we can wrap the entire application in one component and then all of those child components.

So it could be anything. It could be just to use some examples, it could be one of these ones like navigation. It could be the BottomTabBar. It could reach into the provider and say what is the current user's ID? Or whatever data it needs and then it could have access to that without us actually having to send it on a component-by-component basis. So hopefully that makes a little bit more sense.

So what I am going to do is I have to import the CurrentUserProvider here and you can import it a couple different ways. I'm going to show you once again how to import it just with that auto complete one. So I'm going to say CurrentUserProvider. Oh, and it wanted to bring in the context. CurrentUserProvider. There we go. We can get rid of the context one. And then the way that you can do this is you can just say I want to put in this AppContainer inside of it and then I want to return all of this. So I'll say return and then in, make sure you're using parentheses, I'm going to wrap the CurrentUserProvider with the AppContainer inside of it and then I'm going to close it out.

App.tsx

  return (
    <CurrentUserProvider>
      <AppContainer />
    </CurrentUserProvider>
  );

Now, if I hit Save, you can see we don't have any errors so all of that's looking good. Now, let's actually test this out. Before we start getting into calling the API and getting the current user, anything like that, let's just make sure that this works and so we can test this out by opening up our AuthScreen here. So say in the AuthScreen, say we needed access to the current user. Now, in this case, it wouldn't make sense because if they're on the AuthScreen, it means the user isn't signed in but just to make it easy to test out, let's say that we want to have access to that.

So the way we could do that is let's go up and inside of useState, let's do something like let's call useEffect. So I'm going to say useEffect. Or actually you know what? There's an easier way of doing this. So for useState let's just say useContext. So I'm going to grab the context and then we have to import that. So here I'll say import CurrentUserContext from ../../context and then CurrentUserContext. And just as a reminder, the way it works, when you want access to the data, the rule of thumb is you first wrap whatever components need to get that access up in a provider. Then when you want the access, so on that component-by-component basis, then you call the context and you import that.

So now we have to use our useContext hook and I'm going to just bring it up over here because this is all just for demo. We're going to use it. We're going to get rid of this code in a little bit and so you don't even technically, you don't even have to follow along at this point. I'm just wanting to show you how you can get access to this data. So here, for const, I'm going to do some destructuring. So I'll say currentUser inside of curly braces, equals useContext and then CurrentUserContext. No errors, everything's working here.

Okay, so how can we make this work? Well, I'm going to show you something that's kinda cool when you're trying to do debugging because if I just try to print out an object here on the screen, then I'd get an error because you can't print out objects in JSX or TSX can't render an object. So what I can do though, and I do this a lot when I'm working on projects and doing debugging is I'm going to go down below these buttons and all of that and I'm going to create a view here. And inside of the view, I'm going to add a Text tag and I'm going to make sure that we can see it so I'll say the style's going to be color: white and then inside of the Text tag, I'm going to use the curly bracket. Lemme scroll up here just so it's a little easier to see. And I'm going to say JSON, all caps, .stringify and then I'll say currentUser.

Okay, let's see if this works. So I'm going to hit Save here. And there you go. Look at that. We have access to the data coming from our currentUser.

large

So this is incredibly powerful. Now, if you're relatively new to React, say within the last few months or something like that, this may not seem like a big deal. I can tell you though, if you have been building React applications like I have for a couple of years, doing what we just did right now would have taken a very long time. In order to give some child component way down the line, like the AuthScreen component, the ability to reach in and grab a value from essentially a global state was very tricky and required quite a bit more boilerplate code.

But instead, with just really just if we look at it, we only have 24 lines of code here in the CurrentUserProvider, really just about three or four in the context. Any other part of our application that wants to be able to grab and reach in and grab that currentUser now can do it by just doing what we did here. By simply saying hey, I want to use the context API, so I'm using that useContext hook. Then from there, I'm calling it, so I have to import it. I'm calling it and I'm extracting out one of the data points. In this case, it's the currentUser.

You may be building an application that has alerts and you want to have like the little red dot. You want to count those alerts. You could reach in, if your API pass in the alert count, you could reach in to a alert context and grab that. Whenever I'm building an application and it has to have a feature like that, what we just did here is exactly the way I build it. So I am going to be able to use any business logic related to data inside of this provider. So I could call the API and I could get the user, the full user data and we're going to be doing that in the next few videos and I could bring that data down. From that point, any other part of the application that needs it can have access to it with just a couple lines of code.

So this is a really nice way, this was an amazing improvement when React gave us the ability to use the context API to be able to have shared data across the entire application. So hopefully that's making sense to you. If not, don't worry because we are going to be working through this over the next few guides as we build out this entire system and hopefully by the end of that, it's really going to make sense to you how powerful this tool is and how you can use it in your own applications.

Resources