Sharing State with `useContext` in React

Escape the tangled web of "prop drilling" and learn to share state cleanly across your entire application.

🔗

Welcome! Let's solve one of React's most common problems: sharing data across your app.

/* 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:

<ThemeContext.Provider value="dark">
const theme = useContext(ThemeContext);
const ThemeContext = createContext('light');

Completa el código:

Create the channel______
Broadcast the value______
Receive the value______
Unlock with Premium

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>;
}
Unlock with Premium

Practice Example: Code Editor

Complete the code. Create a `ThemeContext`, provide the value "dark", and use it in `ThemedButton` to set its background color.

Enunciado:

Notice how ThemedButton gets the 'dark' theme without any props being passed to it.

* Escribe el código a continuación. Los caracteres correctos se mostrarán en verde y los incorrectos en rojo.

import React, { createContext, useContext } from 'react'; const ThemeContext = createContext('light'); function ThemedButton() { const theme = useContext(ThemeContext); const style = { background: theme === 'dark' ? '#333' : '#FFF', color: theme === 'dark' ? '#FFF' : '#333', padding: '10px 20px', border: '1px solid #333', borderRadius: '5px' }; return <button style={style}>I am a {theme} button</button>; } function App() { return ( <ThemeContext.Provider value="dark"> <ThemedButton /> </ThemeContext.Provider> ); }

Unlock with Premium

Knowledge Check

What problem does the Context API primarily solve?


Unlock with Premium

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>
)
Welcome, Alice

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.