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.
What is React Context?
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
useContextmake 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.
Why use React context?
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.
How does React context work?
React Context relies on the Context API introduced in React 16.3. It involves three main steps:
Creating a context using the
createContextmethod. This method creates a Context object and can optionally include a default value:
import { createContext } from 'react';const CustomThemeContext = createContext("defaultValue");
Using the
Providercomponent to wrap components that need access to the Context. It supplies the data through thevalueprop.
<CustomThemeContext.Provider value="gray"><ChangeTheme /></CustomThemeContext.Provider>
Retrieve data using the
useContexthook—a simpler way to consume context values, replacing the olderConsumercomponent:
const themeData = useContext(CustomThemeContext);
Learn more React context, by trying this project, Markdown Editor Application in React Using Context APIs and Hooks.
A practical example of React context
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.
Creating and providing context
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;
Explanation
Line 1: We import
useStateandcreateContextfrom React.Line 4: We use
createContextto 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
backgroundThemewith an initial value of"light".Line 10: The
CustomThemeContext.Providermakes the theme value (backgroundTheme) and the updater function (setBackgroundTheme) available to all child components. Thevalueprop passes these two variables as an object{backgroundTheme,setBackgroundTheme}.Line 12:
ChangeThemeis a child component wrapped within the provider, meaning it will have access to the context values.
Consuming context with the useContexthook
Now, 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>);}
Explanation
Line 4: We use
useContextto access thebackgroundThemeandsetBackgroundThemevalues fromCustomThemeContext. Now, theChangeThemecomponent has access to both the current theme and the function to change it.Lines 6–8: We define a function,
changeThemethat 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
onClickhandler that triggerschangeThemewhen clicked. The button'sstyledynamically sets thebackgroundcolor based on the current theme. The button text shows the target theme (e.g., “Switch to Dark Theme” if the current theme is light).
Code example
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.
React context vs. Redux
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. |
Advantages of React context
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
useContexthook.Works seamlessly with React's rendering model without adding significant overhead.
Limitations of React context
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.
Conclusion
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.
Frequently asked questions
Haven’t found what you were looking for? Contact Us