useContext
in React with Two Practical Mini-Projects
Introduction
In React, managing data between components is essential, especially in larger applications where multiple components need access to the same data. Prop drilling—passing props down multiple levels of a component tree—can quickly become cumbersome. This is where React's useContext
hook shines. useContext
allows you to share data across components without manually passing props, making it an invaluable tool for state management.
In this article, we’ll start with a detailed explanation of useContext
, its syntax, and its benefits. Then, we’ll solidify this understanding by building two mini-projects:
-
Theme Switcher: A simple theme toggler to show how
useContext
manages global state. -
User Authentication Status: An app to handle user login state, demonstrating how to use
useContext
for real-world use cases.
By the end of this tutorial, you’ll be well-equipped to use useContext
confidently in any React project.
What is useContext
?
The Basics of useContext
useContext
is a React hook that allows components to subscribe to a context directly. It helps avoid the hassle of prop drilling by enabling components to access global data from the nearest provider above it in the component tree.
Syntax of useContext
Here’s the basic syntax for creating and using a context:
import React, { useContext, createContext } from 'react';
const MyContext = createContext(defaultValue); // Step 1: Create a context
function MyComponent() {
const contextValue = useContext(MyContext); // Step 2: Use the context
return <div>{contextValue}</div>;
}
Explanation
-
Creating a Context:
createContext
initializes a context object, which holds the data we want to share. ThedefaultValue
parameter is optional but can be used as a fallback if noProvider
is found. -
Using the Context with
useContext
: Inside a component, we useuseContext(MyContext)
to access the context's current value. This value is determined by the nearest<MyContext.Provider>
above the component in the component tree.
Example of a Context Provider and Consumer
import React, { useContext, createContext } from 'react';
const ThemeContext = createContext('light'); // default theme is light
function ThemeProvider({ children }) {
return <ThemeContext.Provider value="dark">{children}</ThemeContext.Provider>;
}
function DisplayTheme() {
const theme = useContext(ThemeContext); // Consuming the context
return <p>The current theme is {theme}</p>;
}
function App() {
return (
<ThemeProvider>
<DisplayTheme />
</ThemeProvider>
);
}
In this example:
-
ThemeContext
is our context, initialized with a default value of'light'
. -
ThemeProvider
wrapsDisplayTheme
and provides avalue="dark"
, making'dark'
the current theme within theThemeProvider
. -
DisplayTheme
component usesuseContext(ThemeContext)
to access the theme and render it.
This covers the basics. Now, let’s dive into the projects to apply this knowledge in practical scenarios.
Mini Project 1: Building a Theme Switcher
Our first project is a simple theme switcher that will demonstrate how useContext
can be used to manage global application state for themes.
Step 1: Set Up the Context
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
Here, ThemeContext
provides two values: the current theme and a function to toggle it. The provider wraps the app components, making the theme and toggle function available globally.
Step 2: Consume the Context in Components
function ThemeToggler() {
const { theme, toggleTheme } = useContext(ThemeContext); // Access context values
return (
<button onClick={toggleTheme}>
Switch to {theme === 'light' ? 'dark' : 'light'} mode
</button>
);
}
function DisplayTheme() {
const { theme } = useContext(ThemeContext);
return <p>Current Theme: {theme}</p>;
}
Step 3: Use the Provider in the Main App
function App() {
return (
<ThemeProvider>
<DisplayTheme />
<ThemeToggler />
</ThemeProvider>
);
}
export default App;
Now, you can toggle between light and dark themes by clicking the button, with the theme status displayed alongside. This project demonstrates how useContext
allows multiple components to share and react to global state changes.
Mini Project 2: Managing User Authentication
For the second project, let’s build a simple app that tracks a user’s authentication status using useContext
.
Step 1: Create an Auth Context
import React, { createContext, useContext, useState } from 'react';
const AuthContext = createContext();
export function AuthProvider({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const login = () => setIsAuthenticated(true);
const logout = () => setIsAuthenticated(false);
return (
<AuthContext.Provider value={{ isAuthenticated, login, logout }}>
{children}
</AuthContext.Provider>
);
}
Step 2: Create Login and Logout Components
function LoginButton() {
const { login } = useContext(AuthContext); // Access login function
return <button onClick={login}>Login</button>;
}
function LogoutButton() {
const { logout } = useContext(AuthContext); // Access logout function
return <button onClick={logout}>Logout</button>;
}
Step 3: Display User Status
function UserStatus() {
const { isAuthenticated } = useContext(AuthContext);
return (
<p>{isAuthenticated ? 'Welcome back!' : 'Please log in.'}</p>
);
}
Step 4: Combine Components in App
function App() {
return (
<AuthProvider>
<UserStatus />
<LoginButton />
<LogoutButton />
</AuthProvider>
);
}
export default App;
Now, you have a simple authentication status app where the login and logout buttons update the user’s status across the app. This project demonstrates how useContext
can handle state across an application in real-world scenarios.
Conclusion
With these two projects, you’ve seen how useContext
simplifies data sharing between components without the need for prop drilling. The theme switcher and authentication status projects give practical insights into managing global state effectively. Whether you’re toggling themes or handling user authentication, useContext
provides a powerful tool to build efficient and organized applications.