CodeOath
← All posts
React75 min total · 17 parts

React Fundamentals: Components, Hooks, and the Virtual DOM

Contents — Part 12 of 17: The Context API
Part 12 of 17 · ~1 min

The Context API

Context solves prop drilling — passing a value through many layers of components that don't themselves use it — by letting any descendant read a value directly, however deep it's nested.

const ThemeContext = createContext("light");

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

function Toolbar() {
  return <ThemedButton />; // doesn't need to know about theme at all
}

function ThemedButton() {
  const theme = useContext(ThemeContext); // reads directly from the nearest Provider above it
  return <button className={theme}>Click</button>;
}

The performance gotcha

Every component calling useContext(SomeContext) re-renders whenever that context's value changes — regardless of whether that specific component cares about the part of the value that changed. A single large context object holding many unrelated pieces of state ({ user, theme, notifications, ... }) means a change to any one of them re-renders every consumer of the whole context.

The fix is usually splitting one large context into several smaller, more focused ones (UserContext, ThemeContext) so a component only re-renders when the specific piece of state it actually reads changes — or, for very hot paths, pairing context with useMemo on the value it provides, and/or a dedicated state library (Zustand, Redux, Jotai) designed to let components subscribe to just a slice of state.