Use the useContext
hook when there is a need to share states or functions between components without passing them as props. For example, sharing user data or managing themes across components.
Key takeaways:
React Context allows components to share state directly without prop drilling, improving code clarity and reducing manual prop passing.
It is integrated into React and requires no additional dependencies, making it straightforward and efficient for many use cases.
Hooks like useContext
make it easier to manage the global state across components without prop drilling. This makes it easier to share data like themes or user states across components, streamlining your code and improving maintainability.
For apps with simpler state management needs, the React Context offers a cleaner and more straightforward solution than Redux. While Redux is powerful for complex apps, React Context works well when state updates are limited to a few components or involve only a handful of global variables.
React context simplifies state management in React applications by providing a mechanism to share data across components without manually drilling props. Instead of passing data step-by-step, Context allows components to access shared values directly, no matter how deeply nested in the component tree. Unlike traditional state management approaches, React context is lightweight and straightforward for specific use cases like themes, authentication, and localization.
React context addresses a common problem in React—prop drilling. Prop drilling occurs when data needs to be passed through multiple layers of components, even if only the deeply nested components require it. Context provides a solution by offering direct access to the shared state.
React Context relies on the Context API introduced in React 16.3. It involves three main steps:
Creating a context using the createContext
method. This method creates a Context object and can optionally include a default value:
import { createContext } from 'react';const CustomThemeContext = createContext("defaultValue");
Using the Provider
component to wrap components that need access to the Context. It supplies the data through the value
prop.
<CustomThemeContext.Provider value="gray"><ChangeTheme /></CustomThemeContext.Provider>
Retrieve data using the useContext
hook—a simpler way to consume context values, replacing the older Consumer
component:
const themeData = useContext(CustomThemeContext);
Learn more React context, by trying this project, Markdown Editor Application in React Using Context APIs and Hooks.
Let's build an app with a React context to switch between light and dark themes. The theme value will be managed using React’s useState
hook.
We will start with creating a context and providing it to a child component in our application.
import React, { createContext, useState } from 'react';// Create context with a default valueconst CustomThemeContext = createContext("light");function App() {const [backgroundTheme, setBackgroundTheme] = useState("light");return (<CustomThemeContext.Provider value={{backgroundTheme,setBackgroundTheme}}><ChangeTheme /></CustomThemeContext.Provider>);}export default App;
Line 1: We import useState
and createContext
from React.
Line 4: We use createContext
to create a new context object, CustomThemeContext
. We provide "light"
as the default value. If no <Provider>
is found above in the component tree, this value will be used when a component consumes the context.
Line 7: We declare a state variable called backgroundTheme
with an initial value of "light"
.
Line 10: The CustomThemeContext.Provider
makes the theme value (backgroundTheme
) and the updater function (setBackgroundTheme
) available to all child components. The value
prop passes these two variables as an object {backgroundTheme,setBackgroundTheme}
.
Line 12: ChangeTheme
is a child component wrapped within the provider, meaning it will have access to the context values.
useContext
hookNow, let’s create a component that consumes the theme context and allows users to toggle between themes.
import React, { useContext } from 'react';function ChangeTheme() {const { backgroundTheme, setBackgroundTheme } = useContext(CustomThemeContext);function changeTheme() {setBackgroundTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));};return (<buttononClick={changeTheme}style={{background: backgroundTheme === "light" ? "#fff" : "#555",color: backgroundTheme === "light" ? "#000" : "#fff",}}>Switch to {backgroundTheme === "light" ? "Dark" : "Light"} Theme</button>);}
Line 4: We use useContext
to access the backgroundTheme
and setBackgroundTheme
values from CustomThemeContext
. Now, the ChangeTheme
component has access to both the current theme and the function to change it.
Lines 6–8: We define a function, changeTheme
that checks the current theme, prevTheme
. If the theme is "light"
, it switches it to "dark"
, and vice versa.
Lines 11–19: We render a button with an onClick
handler that triggers changeTheme
when clicked. The button's style
dynamically sets the background
color based on the current theme. The button text shows the target theme (e.g., “Switch to Dark Theme” if the current theme is light).
Let's look at a working example by combining everything and executing the application.
Implement the useContext
hook in a real-world application in this project, Build a Location Tracker Using Leaflet, ReactJS, and Express.js.
Apart from React context, we can also Redux to manage the global state of an application or a feature. Redux is a powerful tool for large-scale state management but comes with more boilerplate.
React context and Redux are popular tools for state management in React applications. While both aim to manage shared states effectively, they cater to different levels of complexity and use cases. Let's look at the differences in the table below.
Feature | React context | Redux |
Purpose | Manage simple, shared state like themes or user data. | Manage complex, global state with advanced features. |
Boilerplate | Minimal setup with the Context API. | Requires significant setup (actions, reducers, store). |
Data Flow | Unidirectional, using | Unidirectional, using dispatch and reducers. |
Performance Optimization | Needs manual memoization of context values. | Built-in mechanisms for optimizing re-renders. |
Scalability | Best for small to medium apps. | Suitable for large-scale applications. |
React context offers several benefits, particularly for smaller-scale applications.
No need to use external libraries, e.g., Redux, reducing dependencies and simplifying project setup.
Context eliminates the need to pass props manually through every component level.
Easy to understand and implement, especially with the useContext
hook.
Works seamlessly with React's rendering model without adding significant overhead.
Despite its simplicity, React context has some limitations that may affect its suitability for large-scale applications.
Context re-renders all consuming components when the provider’s value changes. This can lead to performance bottlenecks in large trees.
Managing a complex state with Context alone can become cumbersome without middleware or advanced tools.
Debugging deeply nested components relying on multiple contexts can be challenging without specialized tools.
Unlike Redux, React context does not natively support middleware for asynchronous operations or side effects.
React context is a valuable tool for managing the global state in a React application. While it may not replace state management libraries like Redux, its simplicity and integration make it an excellent choice for many use cases. By following best practices and leveraging hooks, you can maximize the potential of React context in your projects.
Haven’t found what you were looking for? Contact Us