Back
LearnReact — Build Modern Web AppsuseContext — share state without prop drilling

useContext — share state without prop drilling

2 min read

The problem: prop drilling

Imagine your app's theme, or the logged-in user. Many components deep in the tree need it. Passing it as a prop through every layer — parent → child → grandchild → … — even through components that do not use it, just to pass it along. This tiresome passing is called prop drilling, and it makes code messy.

Context solves it: put data in one place and let any component read it directly, no matter how deep.

Three steps to use Context

1. Create the context:

import { createContext } from "react";
export const ThemeContext = createContext();

2. Provide a value at the top, wrapping your app:

function App() {
  const [theme, setTheme] = useState("dark");

  return (
    <ThemeContext.Provider value={theme}>
      <Page />
    </ThemeContext.Provider>
  );
}

3. Consume it anywhere below, with useContext:

import { useContext } from "react";
import { ThemeContext } from "./ThemeContext";

function Button() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>Click</button>;
}

No matter how deep Button is, it reads theme directly — no drilling through every parent.

When should I use Context?

For global-ish data that many components need: the current user, theme, language, or a shopping cart.

A word of caution: do not put everything in Context. For data used by just one or two nearby components, plain props (or lifting state up) are simpler. Context is for truly shared, app-wide data.

Context lets any component read shared data directly, skipping prop drilling. Create it, wrap your app in a Provider with a value, and read it with useContext. Use it for app-wide data like user or theme.

Tip