Skip to content

React Context API

In this article, we will learn about the React Context API and how it can be used to manage global state in a React application.

What is the React Context API?

The React Context API is a way to pass data through the component tree without having to pass props down manually at every level. It allows you to share data between components without having to explicitly pass it through the props of each component.

The Context API consists of two main components:

Basic structure of Context API

There are 3 basic steps to use the Context API

  1. Create a new context object
  2. Create a provider component
  3. Consume the context using a consumer component

Example:

// Create a context
const MyContext = React.createContext();
// Create a provider
function MyProvider({ children }) {
  const [state, setState] = React.useState(initialState);

  return (
    <MyContext.Provider value={{ state, setState }}>
      {children}
    </MyContext.Provider>
  );
}
function MyComponent() {
  return (
    <MyContext.Consumer>
      {({ state, setState }) => (
        <div>
          <p>State: {state}</p>
          <button onClick={() => setState(newState)}>Update State</button>
        </div>
      )}
    </MyContext.Consumer>
  );
}

Example: Theme toogle using Context API

src/
├── context/
│   └── ThemeContext.js     # Context creation and custom hook
├── providers/
│   └── ThemeProvider.js    # Provider component with state management
├── components/
│   └── ThemedComponents.js # Components that consume the context
└── App.js                  # Main application component
import { createContext, useContext } from 'react';

// Create the context
export const ThemeContext = createContext();

// Custom hook to use the theme context
export const useTheme = () => {
  const context = useContext(ThemeContext);
  if (context === undefined) {
    throw new Error('useTheme must be used within a ThemeProvider');
  }
  return context;
};
import React, { useState } from 'react';
import { ThemeContext } from '../context/ThemeContext';

export const ThemeProvider = ({ children }) => {
  const [isDark, setIsDark] = useState(false);

  const toggleTheme = () => {
    setIsDark(prev => !prev);
  };

  // The value object contains our state and functions
  const value = {
    isDark,
    toggleTheme
  };

  return (
    <ThemeContext.Provider value={value}>
      {children}
    </ThemeContext.Provider>
  );
};
import React from 'react';
import { Sun, Moon } from 'lucide-react';
import { useTheme } from '../context/ThemeContext';

export const ThemedButton = () => {
  const { isDark, toggleTheme } = useTheme();
  
  return (
    <button 
      onClick={toggleTheme}
      className={`p-4 rounded-lg flex items-center gap-2 ${
        isDark 
          ? 'bg-gray-800 text-white' 
          : 'bg-blue-100 text-gray-800'
      }`}
    >
      {isDark ? <Moon size={20} /> : <Sun size={20} />}
      Toggle {isDark ? 'Light' : 'Dark'} Mode
    </button>
  );
};
import React from 'react';

import { ThemeProvider } from './providers/ThemeProvider';
import { ThemedButton } from './components/ThemedButton';

const App = () => {
  return (
    <ThemeProvider>
      <div className="p-8">
        <h1 className="text-2xl font-bold mb-4">
          Theme Context Example
        </h1>
        <ThemedButton />
      </div>
    </ThemeProvider>
  );
};

export default App;

References