React

Chapter 10: Context API & State Sharing — Solving prop drilling, createContext, Provider patterns, useContext hook, custom context wrappers, and performance tuning.

1. The Prop Drilling Problem & Why Context Exists

In standard React applications, data is passed top-down via props. When deeply nested components (like a UserAvatar on line 500) need access to global state (like theme or currentUser), you are forced to pass props through dozens of intermediate components that don't even use the data. This is called Prop Drilling.

💡 Real-World Analogy: Radio Broadcast Tower vs Passing Notes in Class

Think of distributing news to everyone in a stadium:

  • Prop Drilling (Passing Notes): You hand a piece of paper to the person next to you, who hands it to the next person, through 50 rows of people until it reaches row 50. Fragile, tedious, and messy!
  • React Context (Radio Broadcast Tower): The parent installs a radio broadcast tower (Provider). Any component anywhere in the stadium can simply tune their antenna to that frequency (useContext hook) and receive the broadcast instantly without bothering anyone else!

2. The 3 Core Steps to Using React Context

The React Context 3-Step Lifecycle
1. createContext() Define Context object const ThemeCtx = createContext() 2. <Context.Provider> Wrap component subtree <ThemeCtx.Provider value={...}> 3. useContext() Consume in any child const theme = useContext(ThemeCtx)

Complete Production Implementation

// 1. Create Context with default value
const ThemeContext = React.createContext("light");

// 2. Wrap App with Provider at high level
function App() {
    const [theme, setTheme] = React.useState("dark");

    return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
            <Header />
            <MainDashboard />
        </ThemeContext.Provider>
    );
}

// 3. Consume anywhere deep inside the tree without props drilling!
function ThemeToggleButton() {
    const { theme, setTheme } = React.useContext(ThemeContext);

    return (
        <button 
            onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
            className={`btn-${theme}`}
        >
            Current Theme: {theme.toUpperCase()}
        </button>
    );
}
Rendered Context Consumer Output:
← Consumed via useContext(ThemeContext)

3. The Custom Provider & Custom Hook Pattern

In enterprise applications, never export raw Context objects directly. Instead, encapsulate the Provider and expose a clean, type-safe custom hook (e.g. useAuth()):

// AuthContext.jsx
const AuthContext = React.createContext(null);

export function AuthProvider({ children }) {
    const [user, setUser] = React.useState({ name: "Anshuman", role: "admin" });

    const login = (userData) => setUser(userData);
    const logout = () => setUser(null);

    return (
        <AuthContext.Provider value={{ user, login, logout, isAuthenticated: !!user }}>
            {children}
        </AuthContext.Provider>
    );
}

// Custom consumer hook with safety guard:
export function useAuth() {
    const context = React.useContext(AuthContext);
    if (!context) {
        throw new Error("useAuth must be used within an AuthProvider!");
    }
    return context;
}
Custom Hook Verification Output:
[AuthProvider] Broadcast state: { isAuthenticated: true, user: "Anshuman" } [useAuth Hook] Validated Context inside AuthProvider tree -> Access granted!

4. Hands-On Practice Challenges

Master global state management and Context provider architectures with these interactive challenges. Click "Solve Challenge" to open the workspace!

🎯 Hands-on Coding Challenge Context Architecture

Challenge 1: Replicate the Context API Architecture

Write a factory function createMiniContext(defaultValue) that returns a Provider(newValue) and useContext() consumer function.

📋 Requirements & What to Write:
  • Store currentValue initialized to defaultValue.
  • Provider(newValue) updates current value and notifies subscribers.
  • useContext() returns the current value.
Expected Result: Initial Context Value: "light" | Updated Context Value: "dark"
💡
Editor Instructions: Complete createMiniContext to manage shared state across components.
miniContext.js
Console / Terminal Output
// Output will appear here when you click "Run Code"...
🎯 Hands-on Coding Challenge Guard Patterns

Challenge 2: Context Guard Hook Validator

Write a guard validator validateContextConsumer(contextValue, hookName) that throws a descriptive error if the consumer is accessed outside its Provider.

📋 Requirements & What to Write:
  • Check if contextValue === undefined || contextValue === null.
  • Throw descriptive error message containing hookName.
  • Otherwise return the valid contextValue safely.
Expected Result: Caught Expected Error: [Context Guard]: useAuth must be wrapped inside its corresponding ContextProvider!
💡
Editor Instructions: Throw an error when context is missing to protect consumer hooks.
contextGuard.js
Console / Terminal Output
// Output will appear here when you click "Run Code"...
🎯 Hands-on Coding Challenge Enterprise Auth Store

Challenge 3: Full AuthContext Store Simulation

Implement an createAuthStore() object containing getState(), login(userProfile), and logout() to simulate an enterprise AuthProvider.

📋 Requirements & What to Write:
  • Encapsulate authState = { user: null, isAuthenticated: false }.
  • login(userProfile) updates user and sets isAuthenticated: true.
  • logout() resets state back to null and false.
Expected Result: State: { user: { id: 101, name: "Anshuman Singh", ... }, isAuthenticated: true } | State after logout: { user: null, isAuthenticated: false }
💡
Editor Instructions: Complete createAuthStore with login/logout action dispatchers.
authStore.js
Console / Terminal Output
// Output will appear here when you click "Run Code"...