Sharing State with `useContext` in React
Escape the tangled web of "prop drilling" and learn to share state cleanly across your entire application.
/* Preparing to simplify state management... */
The Problem: Prop Drilling
Imagine a large component tree where a top-level component holds data that a deeply nested component needs. Passing this data down through every intermediate component via props is called "prop drilling." It's tedious, error-prone, and makes components less reusable.
Step 1: Create a Context
The first step is to create a Context object using React.createContext()
. Think of this as creating a public channel for your data. You can provide a default value, which is used if a component tries to consume the context without a `Provider` above it.
Step 2: Provide a Value
Next, you wrap a parent component in the component tree with the Context's Provider
component. This Provider
accepts a Provider prop, which is the data you want to make available to all components inside it. Anything rendered within this Provider can now "subscribe" to context changes.
Step 3: Consume the Value with useContext
Finally, any functional component inside the `Provider` can access the data using the `useContext` hook. You simply pass the Context object you created to `useContext()`, and it returns the current context `value`. When the `value` in the `Provider` changes, this component will automatically re-render.
Practice Zone
Interactive Test 1: Match the Concept
Match the `useContext` step to its correct code snippet.
Arrastra en el orden correspondiente.
Arrastra las opciones:
Completa el código:
Interactive Test 2: Complete the Code
Rellena los huecos en cada casilla.
import { createContext, useContext } from 'react'; // 1. Create the context const UserContext = (null); function App() { const user = { name: 'Alice' }; return ( // 2. Provide the value <UserContext. value={user}> <UserProfile /> </UserContext.Provider> ); } function UserProfile() { // 3. Consume the value const user = (UserContext); return <h1>Welcome, {user.name}!</h1>; }
Practice Example: Code Editor
Complete the code. Create a `ThemeContext`, provide the value "dark", and use it in `ThemedButton` to set its background color.
Context in Action
Context is more than just a state container; it's a powerful tool for building decoupled and maintainable components. Here's how it's used in real-world scenarios.
1. Global Theme Switching (UI State)
One of the most popular uses for Context is managing a global UI theme (e.g., light/dark mode). You can store the current theme and a function to change it in a context, allowing any component to adapt its styling accordingly.
// ThemeContext.js
export const ThemeContext = createContext();
// App.js
const [theme, setTheme] = useState('light');
<ThemeContext.Provider value={{ theme, setTheme }}>
<MyApp />
</ThemeContext.Provider>
// Any component...
const { theme, setTheme } = useContext(ThemeContext);
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
2. User Authentication (Application State)
Context is perfect for sharing the current user's session data across the application. A top-level provider can hold the user object. Components like the navbar, profile page, and content sections can then consume this context to display user-specific information or render conditionally.
// AuthContext.js
const { currentUser } = useContext(AuthContext);
return (
<nav>
{currentUser ? <p>Welcome, {currentUser.name}</p> : <a href="/login">Login</a>}
</nav>
)
3. A Word of Caution: Performance
Because any component using a context will re-render whenever the context's `value` changes, it's wise to be careful. Avoid placing rapidly changing state (like form inputs) into a global context. Split contexts into logical pieces (e.g., `ThemeContext`, `AuthContext`) to prevent unnecessary re-renders across your app.
Practical Takeaway: Use Context to share state that is truly "global" for a tree of components. For local state, stick with `useState`. This balance is key to a well-architected React application.
Context API Glossary
- Context API
- A React feature that allows you to share state across the entire app (or a part of it) lightly and without having to pass props down manually through the component tree.
- `createContext(defaultValue)`
- The function used to create a Context object. This object contains two components: `Provider` and `Consumer`.
- <MyContext.Provider value=...>
- A component that wraps a part of your component tree. It accepts a `value` prop that will be passed down to all consuming components.
- `useContext(MyContext)`
- A hook that lets a functional component subscribe to context changes. It reads and returns the current value from the nearest matching `Provider` above it in the tree.
- Prop Drilling
- The process of passing data from a parent component to a child component deep down in the tree by passing it through all intermediate components as props. Context is the primary solution for this problem.