DEV Community

Elizabeth
Elizabeth

Posted on • Updated on

Understanding useContext in React

useContext

In React, context is more like a global variable that can be used across all components in an application. An example of when to use the context hook is to set the preferred theme or to store the currently signed-in user.

You should use the context hook only when you need some data to be accessible by many components.

working with useContext

To understand useContext better we'll be creating a context that stores a user's details and we'll be showing some things to the user if their details are stored in the context.

First things

You should have a react app created already and install react-router-dom from npm (just for this example, you don't need react-router-dom for useContext). Now create a file in your source folder and name it userDetails.jsx this is the file that will be creating the context. Then do this.

import { useState, createContext, useMemo } from 'react';

const UserContext = createContext(); 

const UserProvider = (props) => {
    const [username, setUsername] = useState('');
// the state that we'll be storing the username into

/* because we will be providing an object to the provider, it is better to put the value inside a useMemo so that the component will only re-render when there's a change in the value. */

const value = useMemo(
   () => ({username, setUsername}),[username])


    return (
        <UserContext.Provider
            value={value}
        >
            {props.children}
        </UserContext.Provider>
    );
}
export { UserContext, UserProvider };

Enter fullscreen mode Exit fullscreen mode

In the code above, we just created a context called UserContext using react's createContext(), create context will tell react that we want to create a global variable. Then we created a component that contains the state we want to access globally. You'll notice that we're using a provider from the UserContext. UserContext.Provider The provider is a method from useContext that we can warp all the other components in like we're about to do in our App component.

You will also notice that we used the useMemo hook to store the values in the provider, this is to prevent the app from re-rendering when there's no update in the value. (if you aren't familiar with the useMemo hook, don't sweat it because we'll be looking at useMemo in the next section). Erik Westra talked more about that in this post.

In the App.jsx file import the UserProvider that was exported.

import { BrowserRouter, Switch, Route } from "react-router-dom";
import { UserProvider } from './userDetails';

const App = () =>  {
  return (
  <UserProvider>
      <BrowserRouter>
        <Switch>
          <Route path="/" exact component={SetUserDetails} />
          <Route
             path="/user"
             exact
             component={FetchUserDetails} />
        </Switch>
      </BrowserRouter>
    </UserProvider>
 )
}

export default App;
Enter fullscreen mode Exit fullscreen mode

In the code above we're wrapping the provider into our other components. Let's create the components in the Route and use the context inside them.

Create a file and name it SetUserDetails.jsx and paste this in the file

import React, { useState, useContext } from "react";
import { useHistory } from "react-router-dom";
import { UserContext } from "./userDetails";

const SetUserDetails = () => {
  const [name, setName] = useState("");
  const history = useHistory();

  const { setUsername } = useContext(UserContext);
  const handleSetName = () => {
    setUsername(name);
    history.push("/user");
  };
  return (
    <>
      <input 
          value={name} 
          onChange={(e) => setName(e.target.value)} />
      <button onClick={handleSetName}>Set Name </button>
    </>
  );
};

export default SetUserDetails;
Enter fullscreen mode Exit fullscreen mode

In the code above we created a component that accepts a username and stores it into our context. You'll notice the use of the useContext hook. We're using the hook to get the context we created earlier, in this case, we're getting setUsername. Once the user clicks on the button it will assign the name in this local state to the context.

Next, let's get the context. Create a file and name it FetchUserDetails.jsx (this is the other file in the route)

Then paste this into the file.

import React, { useContext } from "react";
import { UserContext } from "./userDetails";

const FetchUserDetails = () => {
  const { username } = useContext(UserContext);

  return <>{username ? `Hello ${username}` : `Hello User`}</>;
};

export default FetchUserDetails;
Enter fullscreen mode Exit fullscreen mode

Here, we're getting the username state and checking for a value in the state. if it is empty we'll display 'Hello User', and if not we'll display the username.

Try running the code and testing it.

You'll notice that the username is available in the other component. Thanks to useContext hook.

Now, try creating a context on your own and also try persisting the context.

Conclusion

This is just a basic usage for useContext there's more you can do with context, like saving a user's preferred theme or some other preferences and persisting it in your local storage.

Thank you for reading.
In my next post, I'd be looking at the useMemo hook.
If you enjoyed this post please like and share. If you have questions please feel free to drop them in the comments section. Keep coding and doing amazing things.

Latest comments (10)

Collapse
 
i_am_eke profile image
Eke Igwe Eke

thanks, very clear and understandable

Collapse
 
imaroof07 profile image
Maroof Lodi

Really helpful, Great post...

Collapse
 
iqrivas profile image
Denisse Rivas

After hours trying to make it work before seeing this, it was so beautiful applying this to my project and see it work like a charm, I used it to show/hide a Purchase modal. Thank you for taking the time to explain this! 💚

Collapse
 
ilizette profile image
Elizabeth

I'm glad it helped!

Collapse
 
alimobasheri profile image
MirAli Mobasheri

Nice article!👍

Collapse
 
rseverinop profile image
Ralph Severino

Great article

Collapse
 
eecolor profile image
EECOLOR

Hi, I noticed a common mistake in your context related code: medium.com/@ewestra/great-article-...

Collapse
 
ilizette profile image
Elizabeth

Thank you for this. I will definitely update the article

Collapse
 
betula profile image
Slava Birch

Great article! Good explanation for better understanding.
I will allow myself to make one suggestion to your article.
To enable syntax highlighting in a code section, you needs to open your code block as

```javascript
code
```
Its will look likes

import { useState, createContext } from 'react';
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ilizette profile image
Elizabeth

Thank you so much