Conceptly
← All Concepts
🌐

Context

State ManagementA shared delivery channel for values needed deep in a component tree

Context is React's way to let deep descendants read shared values directly. A Provider supplies the value to a subtree, and components inside that subtree can read it with useContext without every middle layer manually forwarding props.

Architecture Diagram

🔗 Relationship

Dashed line animations indicate the flow direction of data or requests

Why do you need it?

When the same value is needed in headers, sidebars, and deep content at once, passing it down by hand through each level turns intermediate components into couriers. That delivery burden grows with depth even when those middle components do not care about the value themselves.

Why did this approach emerge?

Component architecture improved reuse, but it also exposed the cost of passing common data through many layers. React answered that pressure not by making all shared values global, but by letting developers explicitly provide common values to a chosen subtree through Context.

How does it work inside?

A Provider makes a value available below it in the component tree. Any descendant that reads the same Context can access the current value directly. When that value changes, the consumers reading it can rerender with the new value.

In Code

A Provider supplying a shared value and a consumer reading it

import { createContext, useContext } from "react";

const ThemeContext = createContext("light");

function SaveButton() {
  const theme = useContext(ThemeContext);

  return <button data-theme={theme}>Save</button>;
}

export function App() {
  return (
    <ThemeContext.Provider value="dark">
      <SaveButton />
    </ThemeContext.Provider>
  );
}

The Provider supplies a value to the subtree, and consumers inside it can read the current value without step-by-step prop passing.

Intermediate components no longer need to forward the value

import { createContext, useContext } from "react";

const AuthContext = createContext<{ name: string } | null>(null);

function UserMenu() {
  const user = useContext(AuthContext);
  return <span>{user?.name}</span>;
}

function Header() {
  return <UserMenu />;
}

export function Shell() {
  return (
    <AuthContext.Provider value={{ name: "June" }}>
      <Header />
    </AuthContext.Provider>
  );
}

Here `Header` neither receives nor forwards the user value, yet `UserMenu` can still read it directly from Context.

What is it often confused with?

Context and props both move values, but their paths differ. Props make the path explicit through parent-child links. Context skips the intermediate delivery steps. That convenience is useful, but it also hides part of the flow, so it works best for genuinely shared values.

When should you use it?

In practice, Context is a good fit for themes, auth identity, organization selection, and form controllers used across a subtree. It is less attractive for values that are only needed a few levels down, because the hidden coupling and rerender scope can become unnecessary overhead.

Sharing theme, current user, and locale settingsReading auth status deep in the treeProviding common configuration to many componentsReducing prop drilling