Skip to content

useContext Hook

useContext reads the nearest value from a React Context Provider above in the tree. It shares data — theme, locale, auth — without passing props through every intermediate component.

Context Provider and Consumer

Create context with createContext(defaultValue), wrap subtrees in <MyContext.Provider value={...}>, and read with useContext(MyContext) in any descendant.

When the provider's value changes, all consuming components re-render. Memoize value objects to avoid unnecessary updates.

const ThemeContext = createContext('light');

function App() {
  const [theme, setTheme] = useState('light');
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  const { theme } = useContext(ThemeContext);
  return <span className={theme}>Tools</span>;
}

Any component under the provider can access theme without prop drilling.

Context API Steps

const Ctx = createContext(defaultValue);
<Ctx.Provider value={currentValue}>...</Ctx.Provider>
const value = useContext(Ctx);
  • Default value used only when no provider exists above.
  • Provider value prop triggers re-renders in consumers when reference changes.
  • Split contexts by update frequency (theme vs user).
  • Custom hooks like useTheme() wrap useContext for ergonomics.

Context Quick Reference

Context API building blocks.

API Role
createContext Create context object
.Provider Supply value to subtree
useContext Read value in descendant
Custom hook useAuth() wraps context access
Split contexts Avoid one giant re-rendering context
vs Redux/Zustand Context for low-frequency global data

Context Performance

A single provider with a large value object that changes often re-renders all consumers. Split into ThemeContext and AuthContext, or use selectors with Zustand for granular subscriptions.

Custom Context Hook Pattern

Export a provider component and useTheme hook from one module. Throw if hook used outside provider for clear errors.

function useTheme() {
  const ctx = useContext(ThemeContext);
  if (!ctx) throw new Error('useTheme must be used within ThemeProvider');
  return ctx;
}

Common Mistakes

  • Putting fast-changing data in wide-reaching context.
  • Creating new object literals in Provider value every render.
  • Using context as a full replacement for Redux without considering perf.
  • Default context value masking missing provider bugs.

Key Takeaways

  • Context shares data across the tree without prop drilling.
  • useContext reads the nearest provider value.
  • Memoize provider values to limit re-renders.
  • Split contexts or use Zustand for frequently changing global state.

Pro Tip

If only two components share state, lift state up instead of reaching for context.