How to Add Light/Dark Mode Toggle Using React Context API
As users become more mindful of their screen time and visual comfort, offering a light/dark theme toggle has become a best practice in modern web design. Dark mode can reduce eye strain, conserve battery life on OLED screens, and improve readability in low-light environments.
With React Context API, you can implement a global theme toggle that is both scalable and easy to integrate into any React app, no external libraries required.
This guide walks you through creating a fully functional theme switcher using React Context, complete with persistent theme preference and styled elements that respond to the current mode.
Why Use React Context for Theme Management?
React Context provides a clean way to share state across multiple components without prop drilling. When managing themes, this makes it ideal for:
- Providing access to the current theme
- Allowing components to toggle between light and dark modes
- Applying conditional styles or class names globally
Step 1: Set Up a New React App
If you’re starting from scratch, use Create React App or Vite:
npx create-react-app theme-toggle-app
# or
npm create vite@latest
Once your project is set up, install it and run:
npm install
npm run dev
Step 2: Create the Theme Context
Inside your src folder, create a file ThemeContext.js:
import { createContext, useContext, useState, useEffect } from 'react';
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState(() => {
return localStorage.getItem('theme') || 'light';
});
useEffect(() => {
document.body.className = theme;
localStorage.setItem('theme', theme);
}, [theme]);
const toggleTheme = () => {
setTheme(prev => (prev === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
return useContext(ThemeContext);
}
This file:
- Initializes the theme from
localStorage - Applies the theme to the
bodyclass - Exposes the
toggleThemefunction for use across the app
Step 3: Wrap Your App in the Provider
In main.jsx or index.js, wrap your app in ThemeProvider:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { ThemeProvider } from './ThemeContext';
import './index.css'; // Import your CSS
ReactDOM.createRoot(document.getElementById('root')).render(
<ThemeProvider>
<App />
</ThemeProvider>
);
Step 4: Add the Toggle Button
Inside App.jsx, use the context to show a toggle button:
import { useTheme } from './ThemeContext';
function App() {
const { theme, toggleTheme } = useTheme();
return (
<div className="app">
<h1>Current Theme: {theme}</h1>
<button onClick={toggleTheme}>
Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode
</button>
</div>
);
}
export default App;
Step 5: Add Theme-Specific Styles
In index.css, use the body.light and body.dark classes to control styling:
body.light {
background-color: #ffffff;
color: #000000;
}
body.dark {
background-color: #121212;
color: #ffffff;
}
button {
margin-top: 1rem;
padding: 0.5rem 1rem;
cursor: pointer;
}
You can also use utility libraries like Tailwind CSS, styled-components, or CSS modules to apply theme-based styles more granularly.
Bonus: Add a Sun/Moon Icon
For better UX, consider using icons (from a library like react-icons) to represent theme states visually.
npm install react-icons
Then update the button:
import { FaSun, FaMoon } from 'react-icons/fa';
<button onClick={toggleTheme}>
{theme === 'light' ? <FaMoon /> : <FaSun />}
</button>
Conclusion
Implementing a light/dark mode toggle in React using Context API provides a clean, reusable, and scalable solution for global theme management. With just a few lines of code, you can offer users a more personalized and comfortable browsing experience, one that persists across sessions and adapts to their preferences.
Whether you’re building a portfolio, blog, or production-level app, this approach keeps your UI flexible, accessible, and future-proof.
Disclaimer
Article written with the help of AI.
Read the full Disclaimer HERE