← Back to all snippets
JAVASCRIPT

Managing Global Theme with React's useContext Hook

Learn how to implement a global theme toggler in React using the useContext hook, effectively avoiding prop drilling for shared state like light/dark mode.

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

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

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

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

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

// 3. Create a Custom Hook to consume the Context (optional but good practice)
export const useTheme = () => {
  const context = useContext(ThemeContext);
  if (context === undefined) {
    throw new Error('useTheme must be used within a ThemeProvider');
  }
  return context;
};

// 4. Example Component using the theme
function ThemedComponent() {
  const { theme, toggleTheme } = useTheme();

  const componentStyle = {
    background: theme === 'light' ? '#eee' : '#333',
    color: theme === 'light' ? '#333' : '#eee',
    padding: '20px',
    borderRadius: '8px',
    textAlign: 'center'
  };

  return (
    <div style={componentStyle}>
      <h1>Current Theme: {theme.toUpperCase()}</h1>
      <button onClick={toggleTheme}>Toggle Theme</button>
      <p>This text changes color with the theme.</p>
    </div>
  );
}

// 5. App usage example
function App() {
  return (
    <ThemeProvider>
      <ThemedComponent />
    </ThemeProvider>
  );
}
How it works: The `useContext` hook in React provides a way to pass data through the component tree without manually passing props at every level (prop drilling). This snippet demonstrates creating a `ThemeContext`, a `ThemeProvider` component to manage and expose the theme state and a toggler function, and a `useTheme` custom hook for easy consumption by any child component within the `ThemeProvider`'s scope. This pattern is excellent for global states like themes, user authentication, or language preferences.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs