Capítulo 32 de 116

Chapter 32: Passing Data Deeply with Context

Core Idea

Context lets a deeply nested component read a value provided by a distant ancestor without every intermediate component having to accept and forward it as a prop — solving "prop drilling," but at the cost of making a component's data dependencies less explicit from its own props alone.

Key Concepts

  • The problem it solves: passing a prop through many layers of components that don't themselves use it, purely to relay it further down, is verbose and brittle — renaming or restructuring the tree breaks the relay chain.
  • Three-part API: createContext(defaultValue) creates a Context object; a <SomeContext value={...}> provider (wrapping a subtree) supplies the actual value for everything inside it; useContext(SomeContext) reads the nearest enclosing provider's value from any descendant, however deep.
  • Nearest provider wins: if multiple providers for the same Context are nested, a consumer reads from the closest one above it — this allows overriding a value for just one subtree (e.g. a different theme for one section of the page).
  • Passes through intermediate components transparently: components between the provider and the consumer don't need to know the Context exists at all — they don't receive or forward anything related to it.
  • Before reaching for Context, consider alternatives: passing props (even through several layers) is fine and keeps data flow explicit — don't reach for Context just to avoid a few layers of prop passing. Extracting a component and passing the JSX itself as children (Ch 15) often eliminates the "relay" layers a different way, without needing Context at all.
  • Good use cases for Context: theming, the current logged-in user/account, routing (current location), and state-management patterns where many components need related state — situations where the value is genuinely "ambient" to a whole subtree, not specific to one parent-child relationship.

Code Examples

const ThemeContext = createContext('light');

function App() {
  return (
    <ThemeContext value="dark">
      <Toolbar /> {/* Toolbar and everything inside it can read 'dark' */}
    </ThemeContext>
  );
}

function Button() {
  const theme = useContext(ThemeContext); // no props passed through Toolbar
  return <button className={theme}>...</button>;
}
  • What it demonstrates: Button, several layers below App, reads theme directly via useContextToolbar in between never touches the value.

Key Takeaways

  1. Context removes the need to relay a prop through components that don't use it — it doesn't replace props for direct parent-child data passing.
  2. The nearest-provider-wins rule is what makes contextual overrides (e.g. a nested "dark section" inside a globally light-themed app) possible.
  3. Overusing Context makes a component's real data dependencies harder to trace from its props alone — reach for it when a value is genuinely ambient to a subtree, not as a default replacement for prop passing.

Connects To

  • Ch 33 (Scaling Up with Reducer and Context): combining Context with useReducer for shared, mutable state across a subtree.
  • Ch 80 (createContext): the full API reference.
  • Ch 50 (useContext): the Hook reference for reading a Context value.