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 };
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;
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;
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;
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.
Top comments (10)
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
Thank you so much
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! 💚
I'm glad it helped!
Nice article!👍
Hi, I noticed a common mistake in your context related code: medium.com/@ewestra/great-article-...
Thank you for this. I will definitely update the article
Really helpful, Great post...
thanks, very clear and understandable
Great article