DEV Community

Cover image for React Context: The Magic Portal for Your App's Data ⛩️✨
Martins Gouveia
Martins Gouveia

Posted on

React Context: The Magic Portal for Your App's Data ⛩️✨

React Context is a feature that allows you to share data across your component tree without having to manually pass props down through every level. This helps solve a problem known as "prop drilling", where a parent component passes data through many intermediate components that don't need it, just so a deeply nested child can receive it.

This is particularly useful for "global" data, such as themes, authenticated user information, or preferred language, which might be needed by many components at different nesting levels.

How Context works

Using React Context involves three main steps:

  1. Create the context: You create a context object using createContext() from React.
  2. Provide the context: You use the Context.Provider component to wrap the section of your component tree where you want the data to be available. The provider accepts a value prop, which contains the data to be shared.
  3. Consume the context: Any component nested within the provider can access the shared data. In modern React, this is done using the useContext hook

Common use cases

Context is ideal for data that is considered "global" to a component tree, such as:

  • Theming: Storing the current theme (e.g., light or dark mode) and making it available to all components.
  • User authentication: Holding the current user's login status and information.
  • Localization: Providing the active language for the application.
  • Global state: For managing a state that affects many different parts of the application, often combined with the useReducer hook.

Example of React Context

1. Create the context
Create a file, ThemeContext.js, to define the context.

// src/contexts/ThemeContext.js
import { createContext, useState, useContext } from 'react';

// Create a new Context with a default value
const ThemeContext = createContext();

// Create a Provider component that will manage the state
export const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');

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

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

// Create a custom hook for easier access to the context
export const useTheme = () => useContext(ThemeContext);`
Enter fullscreen mode Exit fullscreen mode

2. Provide the context
Wrap your application's components with the in your main App.js file.

// src/App.js
import React from 'react';
import { ThemeProvider } from './contexts/ThemeContext';
import Header from './components/Header';
import Content from './components/Content';

function App() {
  return (
    <ThemeProvider>
      <div>
        <Header />
        <Content />
      </div>
    </ThemeProvider>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

3. Consume the context
Now, any component nested inside can use the useTheme hook to access the current theme and toggle it.

// src/components/Header.js
import React from 'react';
import { useTheme } from '../contexts/ThemeContext';

function Header() {
  const { theme, toggleTheme } = useTheme();

  return (
    <header style={{ background: theme === 'dark' ? '#333' : '#eee' }}>
      <h1>My App</h1>
      <button onClick={toggleTheme}>
        Toggle to {theme === 'dark' ? 'Light' : 'Dark'} Mode
      </button>
    </header>
  );
}

export default Header;

// src/components/Content.js
import React from 'react';
import { useTheme } from '../contexts/ThemeContext';

function Content() {
  const { theme } = useTheme();

  return (
    <main style={{ color: theme === 'dark' ? 'white' : 'black' }}>
      <p>The current theme is {theme}.</p>
    </main>
  );
}

export default Content;
Enter fullscreen mode Exit fullscreen mode

When to Use React Context:

Context is suitable for data that is considered "global" or needed by many components at various depths in the component tree. For localized state or prop passing between directly related components, traditional prop passing is often a more straightforward and explicit solution.

Context vs. state management libraries

Context is an effective solution for simple global state and avoiding prop drilling. However, for complex state management, larger applications, or if you need features like advanced debugging, performance-critical updates, or middleware, a dedicated state management library like Redux, Zustand, or MobX may be a better choice.

Top comments (0)