Skip to main content
React Introduction
CHAPTER 20 Beginner

React Context API

Updated: May 13, 2026
25 min read

# React Context API

1. Introduction

React's data flow is strictly top-down (unidirectional). You pass props from Parent to Child. But what happens if a component nested 10 levels deep needs access to the user's login information or the current Light/Dark theme? Passing a prop down through 10 intermediate components is tedious and messy—a problem known as Prop Drilling. The solution built into React is the Context API.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Identify the problem of Prop Drilling.
  • Create a global Context.
  • Provide data using the <Context.Provider>.
  • Consume global data using the useContext hook.
  • Understand when to use Context vs standard State.

3. Beginner-Friendly Explanations

What is Prop Drilling?

Imagine you buy a gift for your great-grandchild. You give it to your child, who gives it to their child, who finally gives it to the great-grandchild. The middle generations don't care about the gift, they are just acting as messengers. This is Prop Drilling.

What is Context?

Context is like a global broadcasting tower. You place a "Provider" at the top of your app (the tower). Any component in your app, no matter how deeply nested, can tune into that broadcast using useContext and access the data instantly, skipping the middle-men completely.

4. Syntax Explanation

Step 1: Create the Context

Create a new file (e.g., ThemeContext.js). We create the context and export it.

```jsx id="ch20_ex1" import { createContext } from 'react';

// 1. Create the Context (The "Radio Station") export const ThemeContext = createContext();

123
### Step 2: Provide the Context
In your main `App.jsx`, wrap the part of your app that needs the data with the Provider.

jsx id="ch20_ex2" import { ThemeContext } from './ThemeContext'; import Navbar from './Navbar'; import MainContent from './MainContent';

function App() { // 2. Wrap components in Provider and pass a 'value' return ( <ThemeContext.Provider value="dark"> <Navbar /> <MainContent /> </ThemeContext.Provider> ); }

123
### Step 3: Consume the Context
Deep inside `MainContent.jsx`, or any other child component, use the `useContext` hook to access the value.

jsx id="ch20_ex3" import { useContext } from 'react'; import { ThemeContext } from './ThemeContext';

function Footer() { // 3. Tune into the Context const theme = useContext(ThemeContext);

return ( <footer className={theme === 'dark' ? 'bg-black text-white' : 'bg-white text-black'}> Current theme is {theme} </footer> ); }

123456789101112131415161718192021222324
## 5. Output Explanations
Even though `Footer` was never passed a `theme` prop directly by its parent, it instantly receives the `"dark"` string from the `ThemeContext.Provider` located at the very top of the app.

## 6. Real-World Examples
Context is NOT meant for data that changes every second. It is meant for "global" configuration data:
- **Authentication:** Current user object, login status, auth tokens.
- **Theming:** Light/Dark mode, user language preferences (i18n).
- **Global Modals:** State determining if a global shopping cart slide-out menu is open or closed.

## 7. Common Mistakes
- **Overusing Context:** Context is not a replacement for regular state. If data is only used by one component and its direct child, just use Props. Context causes all consuming components to re-render when the value changes, which can hurt performance if overused.
- **Forgetting the Provider:** If you use `useContext` but forget to wrap your app in the `<Provider>`, the hook will return `undefined` (or the default value you gave `createContext`), leading to crashes.

## 8. Best Practices
- **Extract Context Logic:** The best practice is to create a custom Provider component that holds its own state. See the Mini Project below for the industry-standard way to write Context.

## 9. Exercises
1. Create a `UserContext` that provides an object: `{ name: "John", role: "Admin" }`.
2. Access the context in a deeply nested component and display "Welcome, Admin John".

## 10. Mini Project: Theme Management System
Here is how professional developers structure Context. We create a dedicated file that manages its own state and exports a custom Provider.

**ThemeContext.jsx**

jsx id="ch20proj1a" // Example React component import React, { createContext, useState, useContext } from 'react';

// 1. Create Context const ThemeContext = createContext();

// 2. Create a Custom Provider Component export const ThemeProvider = ({ children }) => { const [theme, setTheme] = useState('light');

const toggleTheme = () => { setTheme(prev => prev === 'light' ? 'dark' : 'light'); };

// We pass an object containing the state AND the updater function return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); };

// 3. Create a Custom Hook (Best Practice!) // This saves us from having to import useContext AND ThemeContext in every file. export const useTheme = () => useContext(ThemeContext);

1
**App.jsx & Components**

jsx id="ch20proj1b" // Example React component import React from 'react'; import { ThemeProvider, useTheme } from './ThemeContext';

// Deeply nested component const ThemeToggleButton = () => { // Using our custom hook! const { theme, toggleTheme } = useTheme(); return ( <button onClick={toggleTheme} className={px-6 py-2 rounded-full font-bold shadow-md transition-all ${ theme === 'light' ? 'bg-slate-800 text-white' : 'bg-yellow-400 text-slate-900' }} > Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode </button> ); };

const Dashboard = () => { const { theme } = useTheme(); return ( <div className={min-h-screen flex flex-col items-center justify-center transition-colors duration-500 ${ theme === 'light' ? 'bg-slate-100 text-slate-900' : 'bg-slate-900 text-white' }}> <h1 className="text-4xl font-black mb-8">Global State with Context API</h1> <ThemeToggleButton /> </div> ); };

// Main App wrapped in Provider export default function App() { return ( <ThemeProvider> <Dashboard /> </ThemeProvider> ); } ``

11. Coding Challenges

Challenge 1: Create an
AuthContext following the exact pattern above. It should hold a state user (default null) and a function login(username). Create a Login screen that uses the Context to log the user in globally.

12. MCQs with Answers

Q1: What problem does the Context API solve? A) Slow API fetching. B) Prop Drilling (passing props through many intermediate components). C) Routing between pages. *Answer: B*

Q2: Which hook is used to consume data from a Context? A) useState B) useReducer C) useContext D) useGlobal *Answer: C*

13. Interview Questions

  • Q: When should you NOT use the Context API? *(Answer: For data that updates very frequently, like a ticking clock, or data that is only needed locally. State management libraries like Redux or Zustand are better for high-frequency, complex global state).*
  • Q: Describe how to set up the Context API from scratch.

14. FAQs

Is Context API a replacement for Redux? For small to medium applications, absolutely. If all you need is theme, auth, and basic user settings, Context is perfect. However, Redux/Zustand offer better performance and debugging tools for massive enterprise apps with highly complex state logic.

15. Summary

The Context API is a powerful built-in tool for managing global state. By setting up a Context Provider at the root of your application, any component can directly access that data using the
useContext` hook, resulting in cleaner code and eliminating the dreaded "Prop Drilling".

16. Next Chapter Recommendation

We've managed data, but what if we need to directly interact with a raw HTML element, like automatically focusing a text input when a page loads? In Chapter 21: React useRef Hook, we will learn how to bypass the Virtual DOM and grab elements directly.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·