React Context: A Comprehensive Guide - Part 4🔔🔔🔔
Intro to ReactJS basic - Part 1 ☘️☘️☘️
React JS Virtual DOM Explained - Part 2 🌲🌲🌲
Advance React Hooks - Part 3💯💯💯
ReactJS Explained Hooks - Part 5 ⚡️⚡️⚡️
🌐🌐🌐 The useContext
hook is a powerful feature in React that allows functional components to access values from a React Context directly. This eliminates the need to pass props through every level of the component tree, making it easier to share data globally or across deeply nested components.
What is Context?
Before diving into useContext
, it’s essential to understand what Context is in React. Context provides a way to share values (like global state, themes, or user information) between components without having to pass props manually at every level.
Creating Context
To use useContext
, you first need to create a Context object using React.createContext()
. Here's how it works:
Create a Context:
javascriptCopy codeimport React, { createContext } from 'react'; const MyContext = createContext();
Provide Context: Use the
Provider
component to make the context value available to child components.javascriptCopy code<MyContext.Provider value={/* some value */}> <ChildComponent /> </MyContext.Provider>
Consume Context: In any child component, use the
useContext
hook to access the context value.javascriptCopy codeimport React, { useContext } from 'react'; function ChildComponent() { const contextValue = useContext(MyContext); return <div>{contextValue}</div>; }
How useContext
Works
Accessing the Value: When you call
useContext(MyContext)
, it returns the current value of the context. This value is determined by the nearestMyContext.Provider
up the tree.Reactivity: When the value of the context changes (due to a state update in the provider), all components that consume this context using
useContext
will re-render to reflect the new value.
Example of useContext
Here's a complete example demonstrating how to use useContext
in a simple React application:
Step 1: Create a Context
javascriptCopy codeimport React, { createContext, useState } from 'react';
const ThemeContext = createContext();
Step 2: Create a Provider Component
javascriptCopy codefunction 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 3: Use the Context in Child Components
javascriptCopy codeimport React, { useContext } from 'react';
function ThemedComponent() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }}>
<p>The current theme is {theme}</p>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
}
Step 4: Wrap Your Application with the Provider
javascriptCopy codefunction App() {
return (
<ThemeProvider>
<ThemedComponent />
</ThemeProvider>
);
}
Key Points about useContext
Simplifies State Management:
useContext
allows you to avoid "prop drilling," where props need to be passed through many layers of components, improving the structure and readability of your code.Global State Management: It can be used to manage global states (like themes, user authentication, language settings) across the application.
Reactivity: Components that use
useContext
will automatically re-render whenever the context value changes, keeping the UI in sync with the data.Combining with Other Hooks:
useContext
can be combined with other hooks likeuseReducer
oruseState
for more complex state management solutions.
When to Use Context
While useContext
is a powerful tool, it’s best to use it in situations where you need to share data among many components at different levels of the tree. It’s not ideal for local state management or for passing props to just a few components, as it may lead to unnecessary re-renders.
Using useContext
in a React application can have implications for performance, particularly concerning re-renders. Here’s a breakdown of how useContext
affects performance, along with best practices to mitigate potential issues.
How useContext
Can Impact Performance
Re-rendering of Consumer Components:
- When the value provided by a
Context.Provider
changes, all components that consume that context usinguseContext
will re-render. This can lead to performance bottlenecks if the context value is updated frequently or if many components are subscribed to the same context.
- When the value provided by a
Unnecessary Re-renders:
- If a context value changes but only some components need the new value, all consumers of that context will still re-render. This might be inefficient if those components do not rely on the updated value.
Larger Component Trees:
In applications with deep or complex component trees, using context extensively can cause a chain reaction of re-renders that affect performance, particularly if the updates are not optimized.
Example of Optimizing Context Usage
Here’s a simplified example that demonstrates some of these techniques:
javascriptCopy codeimport React, { createContext, useContext, useState, useMemo } from 'react'; // Creating Context const ThemeContext = createContext(); // Provider Component const ThemeProvider = ({ children }) => { const [theme, setTheme] = useState('light'); const toggleTheme = () => { setTheme((prev) => (prev === 'light' ? 'dark' : 'light')); }; // Memoize the context value const value = useMemo(() => ({ theme, toggleTheme }), [theme]); return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>; }; // Consumer Component const ThemedComponent = React.memo(() => { const { theme, toggleTheme } = useContext(ThemeContext); return ( <div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }}> <p>The current theme is {theme}</p> <button onClick={toggleTheme}>Toggle Theme</button> </div> ); }); // App Component const App = () => ( <ThemeProvider> <ThemedComponent /> </ThemeProvider> ); export default App;
Summary
useContext
provides a way to access the value of a context directly in functional components.It simplifies state management and helps avoid prop drilling.
It automatically triggers re-renders in consuming components when the context value changes.
It’s best used for global state or shared data across many components.
Subscribe to my newsletter
Read articles from kietHT directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
kietHT
kietHT
I am a developer who is highly interested in TypeScript. My tech stack has been full-stack TS such as Angular, React with TypeScript and NodeJS.