React context enables us to share and use data across different components in our React app without relying solely on props. In essence, it simplifies the process of passing state information between components. React context helps us to mitigate the issue of props drilling. Props drilling refers to the situation where you pass props down through multiple levels to a nested component, traversing through components that don’t actually need those props.
/ Assume 'appTheme' as the theme prop name
export default function MyApp({ appTheme }) {
return (
<>
<AppHeader appTheme={appTheme} />
<AppMain appTheme={appTheme} />
<AppSidebar appTheme={appTheme} />
<AppFooter appTheme={appTheme} />
</>
);
}
function AppHeader({ appTheme }) {
return (
<>
<AppUser appTheme={appTheme} />
<AppLogin appTheme={appTheme} />
<AppMenu appTheme={appTheme} />
</>
);
}
When is it appropriate to utilize React context?
React context proves beneficial when you need to pass data that can be accessed by any component throughout your application. Examples of such data include:
- Theme Management to share Theme data (such as dark or light mode)
- Localization to share data (like the user’s language or locale)
- Authentication to share user data (information about the currently authenticated user)
It is advisable to store data in React context that doesn’t need frequent updates. Think of React context as global variables within a React app.
While you might consider wrapping your entire app with a Provider to pass all the data, it’s important to note that React context isn’t intended to serve as a comprehensive state management system. The issue arises when every component using the Context re-renders each time the Provider’s value changes, leading to unnecessary re-renders when updating just one piece of data. To mitigate this, it’s recommended to create separate Contexts/Providers for different sections that share data within their respective components. This approach minimizes the number of components that re-render, directing updates specifically to the relevant parts of your app.
How to use React context?
Step 1. create the context
We generate context object using the createContext()
function
import { createContext } from "react";
const MyContext = createContext();
Step2. wrapping the components in a Context Provider
After creating the context object, we utilize it in our components by enclosing the components within a Context Provider.
<MyContext.Provider value={/* some value */}>
{/* Your components */}
</MyContext.Provider>
Step 3. use the context
Any component nested inside the Provider can access the context’s data using the useContext()
.
import { useContext } from "react";
import MyContext from "./MyContext";
function MyComponent() {
const value = useContext(MyContext);
// ...
}
Example 1: sharing the username
import React from 'react';
export const UserContext = React.createContext();
export default function App() {
return (
<UserContext.Provider value="User 1">
<User />
</UserContext.Provider>
)
}
function User() {
const value = React.useContext(UserContext);
return <h1>{value}</h1>;
}
Example 2: Sharing the theme and change it globally
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext(null);
// App component using the ThemeProvider
const App = () => {
const [theme, setTheme] = useState('dark');//default theme
return (
<ThemeContext.Provider value={{ theme, setTheme }}>//note what we have sent here as the value of the context.
<ThemedComponent1 />
<ThemedComponent2 />
</ThemeContext.Provider>
);
};
// Component that consumes the theme context
const ThemedComponent1 = () => {
// Access the theme object from Context
const { theme, setTheme } = useContext(ThemeContext);
return (
<div style={{ backgroundColor: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#333' : '#fff' }}>
<p>Component 1: The current theme is: {theme}</p>
{<button onClick={(e) => {setTheme(theme ==='light' ? 'dark' : 'light')}}>Toggle Theme</button>}
</div>
);
};
const ThemedComponent2 = () => {
// Access the theme object from Context
const { theme, setTheme } = useContext(ThemeContext);
return (
<div style={{ backgroundColor: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#333' : '#fff' }}>
<p>Component 2: The theme for this component is also change since it read the theme from context</p>
</div>
);
};
export default App;
Read more: