Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. React Dictionary
  3. Context

Context

Since: React 16.8(2019)

Context in React is a mechanism for sharing data across the entire component tree without passing props through every intermediate component. It is an efficient way to pass data that is needed by many components — such as logged-in user information, themes, or language settings.

Syntax

// Creating a Context
const MyContext = React.createContext(defaultValue);

// Providing data to the entire tree with a Provider
<MyContext.Provider value={valueToPass}>
  <ChildComponent />
</MyContext.Provider>

// Extracting the value with the useContext hook
const value = useContext(MyContext);

Main Context Elements

ElementOverview
React.createContext()Creates a Context object. The argument specifies a default value used when a consumer is placed outside any Provider.
Context.ProviderA component that provides a value to descendant components. Pass the data you want to share via the value property.
useContext()A hook that retrieves the Context value inside a function component. It receives the value from the nearest Provider above it.
Context.ConsumerA legacy way to access Context values in class or function components using the render prop pattern. Using useContext() is now the standard approach.

Comparison with Props Drilling

MethodOverview
Props DrillingPassing props from parent to child to grandchild in sequence. Intermediate components are forced to receive data they do not use, making the code verbose.
ContextAny descendant of a Provider can read the data directly without going through intermediate components. The more shared data there is, the clearer the code becomes.

Sample Code

An example of sharing a theme color across the entire app and accessing it directly from a deeply nested component.

import React, { createContext, useContext, useState } from 'react';

// Create a Context for sharing theme information
// 'light' is set as the default value
const ThemeContext = createContext('light');

// Helper function that returns a style object based on the theme
function getStyle(theme) {
  return theme === 'dark'
    ? { background: '#333', color: '#fff', padding: '8px' }
    : { background: '#fff', color: '#333', padding: '8px' };
}

// A deeply nested child component
// Gets the theme directly via useContext without receiving it as a prop
function DeepChild() {
  const theme = useContext(ThemeContext);
  return (
    <div style={getStyle(theme)}>
      Current theme: {theme}
    </div>
  );
}

// An intermediate component
// Does not need to pass or receive any theme-related data
function Middle() {
  return (
    <div>
      <DeepChild />
    </div>
  );
}

// Root component
// Wrapping with Provider makes the theme available to the whole tree
function App() {
  const [theme, setTheme] = useState('light');

  // Toggles the theme on button click
  function toggleTheme() {
    setTheme(function(prev) {
      return prev === 'light' ? 'dark' : 'light';
    });
  }

  return (
    <ThemeContext.Provider value={theme}>
      <button onClick={toggleTheme}>Toggle theme</button>
      {/* Middle does not receive theme as a prop */}
      <Middle />
    </ThemeContext.Provider>
  );
}

export default App;

Overview

Context is the official React mechanism for sharing data across the component tree. It is well-suited for managing global data that is needed throughout the application — such as login state, themes, and locale settings.

Overusing Context can reduce component reusability. If the scope of data sharing is limited, consider passing it via props first. On the other hand, when many components across deep nesting levels need the same data, Context is highly effective.

When a Context value changes, all descendant components that reference it will re-render. When passing objects as the value, it is a good practice to optimize with useMemo() to prevent unnecessary re-renders.

Related pages: props / state / Component

Common Mistakes

Without a Provider, the defaultValue is returned

When a component using useContext is placed outside a Provider, the default value passed to createContext is returned. If this happens unintentionally, it can cause bugs. Make sure the component is correctly placed inside the Provider.

ng_example.jsx
const UserContext = createContext({ name: 'Ikari Shinji' });

function Profile() {
  // NG: outside the Provider, so the default value { name: 'Ikari Shinji' } is returned
  const user = useContext(UserContext);
  return <p>{user.name}</p>;
}

function App() {
  // Not wrapped with Provider, so Profile references the default value
  return <Profile />;
}

Fixed:

ok_example.jsx
const UserContext = createContext(null);

function Profile() {
  const user = useContext(UserContext);
  return <p>{user.name}</p>;
}

function App() {
  // OK: wrap with Provider and pass the actual value
  return (
    <UserContext.Provider value={{ name: 'Ayanami Rei' }}>
      <Profile />
    </UserContext.Provider>
  );
}

Passing an object literal directly to value causes re-renders on every render

Writing value={{ user, setUser }} creates a new object on every parent render, causing all Consumers of that Context to re-render every time. Use useMemo to stabilize the object reference, or pass the values returned directly from useState.

ng_example.jsx
function App() {
  const [user, setUser] = useState({ name: 'Soryu Asuka Langley' });

  // NG: a new object is created on every render
  return (
    <UserContext.Provider value={{ user, setUser }}>
      <Main />
    </UserContext.Provider>
  );
}

Fixed:

ok_example.jsx
import { useMemo } from 'react';

function App() {
  const [user, setUser] = useState({ name: 'Soryu Asuka Langley' });

  // OK: stabilize the reference with useMemo to prevent unnecessary re-renders
  var contextValue = useMemo(function() {
    return { user, setUser };
  }, [user]);

  return (
    <UserContext.Provider value={contextValue}>
      <Main />
    </UserContext.Provider>
  );
}

Importing createContext and useContext from the wrong place

Both createContext and useContext are imported from the react package. When using a Context object defined in a separate file, failing to import it correctly will cause errors. Define and export the Context in one place, and import it consistently in every component that uses it.

ng_example.jsx
// NG: forgetting to import the Context from the other file, accidentally creating a new one locally

// UserContext.js
import { createContext } from 'react';
export const UserContext = createContext(null);

// Profile.jsx
import { createContext, useContext } from 'react';
// Wrong: creates a new, different Context with the same name
const UserContext = createContext(null);

function Profile() {
  const user = useContext(UserContext); // cannot get the value
  return <p>{user ? user.name : 'none'}</p>;
}

Fixed:

ok_example.jsx
// OK: import the Context object from the file it was defined in

// UserContext.js
import { createContext } from 'react';
export const UserContext = createContext(null);

// Profile.jsx
import { useContext } from 'react';
import { UserContext } from './UserContext'; // same object imported

function Profile() {
  const user = useContext(UserContext); // value is correctly obtained
  return <p>{user ? user.name : 'none'}</p>;
}

If you find any errors or copyright issues, please .