JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicsreactContext API
PrevNext
react
intermediate
10 min read

Context API

context
dependency-injection
prop-drilling
providers
useContext

Context provides data to any descendant component without passing props through every level — it solves prop drilling but is not state management, and context value changes re-render all consumers.

Key Points

1Solves Prop Drilling

Provides data to any descendant without passing through intermediate components — createContext, Provider, useContext.

2Not State Management

Context is a data distribution mechanism, not a state manager. You still need useState/useReducer for the actual state logic.

3Re-render Behavior

When a Provider's value changes, ALL consumers re-render — even if they only use a part of the context that didn't change.

4Best for Infrequent Changes

Ideal for theme, locale, auth status. Not suited for frequently changing data like typing input or real-time updates.

5Performance Optimization

Split contexts by change frequency, memoize Provider values with useMemo, and wrap consumers with React.memo.

What You'll Learn

  • Explain how the Context API works and what it solves
  • Know when to use Context vs dedicated state management
  • Optimize context performance by splitting and memoizing

Deep Dive

The Context API lets you pass data through the component tree without manually threading props through every intermediate component. It's React's built-in dependency injection mechanism.

How Context Works

Three steps: create, provide, consume.

  1. const ThemeContext = createContext('light') — creates a context with a default value.
  2. <ThemeContext.Provider value={theme}> — wraps a subtree and provides the value to all descendants.
  3. const theme = useContext(ThemeContext) — any descendant reads the nearest Provider's value.

If no Provider exists above the consumer, useContext returns the default value from createContext.

When to Use Context

Context is ideal for data that many components at different nesting levels need, but that changes infrequently:

  • Theme (dark/light mode) — read by every component with styles
  • Locale/language — read by every text component
  • Auth state (current user) — read by navigation, protected routes, profile components
  • UI preferences — font size, reduced motion, sidebar state

When NOT to Use Context

Context is not optimized for frequently changing data. When a Provider's value changes, every component that calls useContext for that context re-renders — even if the specific piece of data they use hasn't changed. For rapidly changing data (typing input, scroll position, real-time updates), use state management libraries (Zustand, Redux) that offer fine-grained subscriptions.

Context Is Not State Management

A common misconception is that Context replaces Redux or Zustand. Context is a data distribution mechanism — it doesn't manage state, handle updates, or provide optimized subscriptions. You still need useState or useReducer to manage the actual state; Context just makes it available without prop drilling. The combination of useReducer + Context can work for simple global state, but it lacks the performance optimizations of dedicated state management libraries.

Performance Optimization

Since all consumers re-render when context value changes:

  • Split contexts: Separate frequently and infrequently changing data into different contexts. ThemeContext and UserContext instead of one AppContext.
  • Memoize the value: If the Provider re-renders for reasons unrelated to the context value, wrap it with useMemo: <Ctx.Provider value={useMemo(() => ({ theme, toggle }), [theme])}>. This prevents new object references from triggering unnecessary consumer re-renders.
  • Memoize consumers: Wrap consumer components with React.memo so they only re-render when their props (including context-derived values) actually change.

React 19: use() with Context React 19 introduces the use() hook, which can accept a context: const theme = use(ThemeContext). Unlike useContext, use() can be called conditionally and works inside try/catch blocks and after early returns.

Key Interview Distinction

Context solves prop drilling — it's dependency injection, not state management. All consumers re-render on any context value change, making it unsuitable for frequently changing data. Split contexts and memoize values for performance. For complex state with frequent updates, use dedicated state management libraries instead.

Fun Fact

The original Context API (React 16.3) replaced an unstable, undocumented context mechanism that had existed since React's early days. The old API was so unreliable that the React team actively warned against using it — but Redux depended on it internally, which is one reason Redux existed in the first place.

Learn These First

Props

beginner

State

beginner

Continue Learning

Unidirectional Data Flow

beginner

State Management

advanced

Hooks

intermediate

Practice What You Learned

What is React Context and when should you use it?
mid
context
Context provides a way to pass data through the component tree without prop drilling. Use it for global data like themes, authentication, or locale. For frequently changing data or complex state logic, consider state management libraries instead.
Previous
Concurrent React
Next
Unidirectional Data Flow
PrevNext