useContext() usage in React
Tags: react, usecontext, component, hooks
Published: 2022-12-31 07:46:57

During the development phase of my React project for my Flatiron Phase 2 project, I came across the need to use a very helpful React hook called `useContext()`.  I found this hook very useful because I needed to share the same data across multiple components in my application and without it I would have been forced to use repeated props in all of the components where I needed to use the information.

To start, the definition of `useContext()` from the React Docs is the following:  "useContext is a React Hook that lets you read and subscribe to context from your component."  The key takeaway from this is that we need to create context FIRST in order to subscribe to it.  And in order to create context we have to use the `createContext()` hook.  

The best way to learn how to work with `useContext()` is by going through an example.  So let's take a look at a use case of how it is implemented and for that I will show an example of how I implemented it in my React project.

First, the issue at hand was that I had implemented a User login feature to the application and I needed a way to keep track of which User is currently logged in.  And this information was needed to be accessible across multiple components in the application, which is essentially what Context is used for.

So in order to implement the logged in User, I created a UserContext as seen below.  As you can see, I've created a context called _UserContext_ and within that context I have a state variable called _loggedInUser_ and a setter function called _setLoggedInUser_ which are used to set & store the User that is logged in.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nibsk5ha3m95ek6wif83.jpg)

Now that we have the Context created, we can utilize it in our React components wherever we need to access this information.  For instance, there is a component named _Login_ which is being used to handle the login functionality that includes setting the logged in User.  Since we have the UserContext created which contains the `setLoggedInUser()` function, we can utilize it in the Login component as follows:

Here we use object destructuring to access the setLoggedInUser function inside Context into our component.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o2puhi90kcdh3xiaq3u9.jpg)

And with that we can now set the logged in User based on the login information entered into the user login form:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5qg9r93bbrwixeaetno.jpg)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1md7zzuwqx8h6wg8pg0l.jpg)

Another use case for this functionality is in the Host component.  One of the features of the Host screen is to allow the logged in User to modify the start and end times that is associated with each individual user. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1oe2dh3j14zo3qe80h56.jpg) 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3fjk4exbj1dusimi7s62.jpg)

By accessing the loggedInUser via the UserContext, we can modify the Start and End times associated with that user as seen below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i1q7rrz1zvwjw02gpw9y.jpg)

So now that we understand what useContext() is used for and have seen a couple of examples of real-world use cases of it you may be wondering:  "What is the advantage of using it?  Can't we just accomplish the same thing with props?"  And the answer to that question is yes we can but it is not nearly as efficient and leads to a lot of repeated code.  

To see an example of this let's look at a real example.  In the App class of the same project, there is a property called _isLoggedIn_ which stores a boolean value representing if there is a User logged in or not.  And similar to the loggedInUser data, the isLoggedIn information is needed in multiple components across the application.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/boc1q54sxz1vo48inr3h.jpg)

Notice here we are using the familiar `useState()` hook to create a variable that will hold this information.  Then to pass this data to other components, we have to pass it as props as seen below:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unk1em29100so0vmwr0g.jpg)

Notice that here we are passing the _isLoggedIn_ property to three different components via props.  And while this may not save much code as we would need to subscribe to Context in these three components if we were using the `useContext()` hook instead, the real advantage would come if we needed to use the _isLoggedIn_ property in nested components within these three components.  In that case, we would need to pass it via props to each of the three parent components and then pass it as props to any children components.  This is referred to as _prop drilling_ and this is where `useContext()` can offer a real advantage to reducing repititous code.

As you've seen, `useContext()` can be a very useful to pass data between components especially in cases where there are many nested layers of components.  With that said, it is considered best practice to utilize `useContext()` sparingly throughout the application and save it for cases where it offers a significant reduction in code repetition.