Previously I shared a post about How Context API fits into Component-driven architecture and shared a small glance of using Context API with a custom hook. This post dives deep into that specific part of the previous entry, this way you can have a broader understanding of the flexibility React offers when using two of its most powerful tools available and ends up offering a powerful solution for state management that simplifies sharing data between components without the need for prop drilling. In this post, we’ll explore how to effectively use the Context API with custom hooks, discuss its benefits, and provide practical examples. Let’s start!
What is the Context API?
The Context API is a feature in React that allows you to share values (state, functions, etc.) across the component tree without having to pass props down manually at every level. This is particularly useful for global data like themes, user authentication, or any other state that needs to be accessible in many components.
Why Combine Context API with Custom Hooks?
- Encapsulation of Logic: Custom hooks can encapsulate the logic of consuming context, making your components cleaner and easier to read.
- Reusability: You can create a custom hook that utilizes the Context API and reuse it across different components, promoting DRY (Don’t Repeat Yourself) principles.
- Separation of Concerns: By separating the logic of accessing context from the component logic, you can enhance maintainability.
Creating a Context with a Custom Hook
Now the part that everyone was waiting for 😜 the code! Let’s see one of the most common use cases the context is being used for: light/dark theme selection. So, let’s start from the beginning.
Step 1: Create the Context
First, you’ll need to create a context for the data you want to share. For this example, let’s create a simple theme context.
import React, { createContext, useContext, useState } from 'react';
// Create a Context
const ThemeContext = createContext();
// Create a Provider Component
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
Step 2: Create a Custom Hook
Next, create a custom hook to use the context easily.
export const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};
Step 3: Using the Provider in Your Application
Wrap your application (or part of it, depending which parts of you application will make use of the context) with the ThemeProvider
to provide context to the components.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { ThemeProvider } from './ThemeContext';
ReactDOM.render(
<ThemeProvider>
<App />
</ThemeProvider>,
document.getElementById('root')
);
Step 4: Consuming the Context with the Custom Hook
Now, you can easily access the theme and the toggle function in any component that is a descendant of the ThemeProvider
.
import React from 'react';
import { useTheme } from './ThemeContext';
const ThemeToggler = () => {
const { theme, toggleTheme } = useTheme();
return (
<div>
<p>Current Theme: {theme}</p>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
};
export default ThemeToggler;
After implementing our theme context, we can see that some of the benefits using this approach are:
- Cleaner Code: Custom hooks reduce boilerplate code in components, making them cleaner and easier to understand.
- Enhanced Reusability: The
useTheme
hook can be reused across any number of components that need access to theme state. - Easier Testing: Encapsulated logic in custom hooks can be tested independently from components, improving testability.
Conclusion
Using the Context API in combination with custom hooks provides a powerful approach to managing state in React applications. This pattern encourages better organization, reusability, and maintainability of your code, making it easier to manage global state effectively. By creating a custom hook for accessing context, you streamline your component logic and enhance the overall structure of your application.
Web developer with over ~6 years of experience. I am a highly motivated and results-oriented developer with a passion for creating scalable and user-friendly web applications. I am recently exploring the world of blogging, hoping to share some of my experience in this exciting and ever-evolving journey of development.