Lesson 30 +10 XP

Consuming Context with useContext

Consuming Context with useContext

Now that we have created a Context and wrapped our application in a Provider, any child component can consume that context data using the useContext hook.

The useContext Hook

The useContext hook receives a Context object (the object returned by createContext) and returns the current context value supplied by the nearest matching <Context.Provider> higher up in the component tree.

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

function ThemeToggleButton() {
  // Access theme state and toggleTheme function directly from context!
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <button onClick={toggleTheme} className={"btn-" + theme}>
      Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode
    </button>
  );
}

Notice that ThemeToggleButton did NOT receive any props! It reads directly from ThemeContext.

Creating Custom Hook Shorthands

To avoid importing both useContext and ThemeContext in every file, export a custom helper hook from your context file.

// Inside AuthContext.jsx
import { createContext, useContext, useState } from 'react';

const AuthContext = createContext();

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}

// In consumer components:
function Navigation() {
  const { user, logout } = useAuth(); // Clean shorthand!
  return user ? <button onClick={logout}>Log out {user.name}</button> : null;
}

When NOT to Use Context

Context is powerful, but overuse can make component reuse harder and cause unnecessary re-renders across large component trees.

  • Do NOT use Context for local component state (like toggle dropdowns or text inputs).
  • Consider component composition (children prop) before reaching for Context for simple prop drilling.

Summary & TL;DR

  • useContext(MyContext) accesses the current context value from the nearest matching Provider.
  • Eliminates prop drilling completely for components consuming context data.
  • Create custom hooks like useAuth() to wrap useContext calls cleanly.