Dark mode is a must-have feature in modern web apps. It enhances user experience and can reduce eye strain. In this post, we'll walk through how to implement a Dark Mode Toggle in a React app using the Context API to manage state globally.
We'll create a simple app where users can toggle between dark and light modes, with their preference stored in localStorage so it persists even after they leave or reload the page.
Step 1: Set up the Context
The first step is to create a ThemeContext that will provide the dark mode state and the toggle function to any component in the app.
// src/context/ThemeContext.js
import React, { createContext, useState, useEffect } from 'react';
export const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [darkMode, setDarkMode] = useState(() => {
const savedMode = localStorage.getItem('dark-mode');
return savedMode === 'true' || false;
});
useEffect(() => {
localStorage.setItem('dark-mode', darkMode);
document.body.className = darkMode ? 'dark-mode' : '';
}, [darkMode]);
const toggleDarkMode = () => {
setDarkMode((prevMode) => !prevMode);
};
return (
<ThemeContext.Provider value={{ darkMode, toggleDarkMode }}>
{children}
</ThemeContext.Provider>
);
};
Here, we're using useState
to initialize the theme based on localStorage
. useEffect
ensures that whenever the theme changes, it updates localStorage
and applies the appropriate class to the body
element.
Step 2: Create the Toggle Component
Here, we use useContext
to consume the darkMode
value and toggleDarkMode
function from the ThemeContext
.
// src/components/ThemeToggle.js
import React, { useContext } from 'react';
import { ThemeContext } from '../context/ThemeContext';
const ThemeToggle = () => {
const { darkMode, toggleDarkMode } = useContext(ThemeContext);
return (
<button onClick={toggleDarkMode}>
{darkMode ? 'Switch to Light Mode' : 'Switch to Dark Mode'}
</button>
);
};
export default ThemeToggle;
Step 3: Apply Dark Mode Styles
To see the dark mode in action, you'll need to add some CSS styles. For simplicity, we'll apply a dark theme to the body
element.
/* src/styles.css */
body {
margin: 0;
font-family: sans-serif;
transition: background-color 0.3s ease;
}
body.dark-mode {
background-color: #121212;
color: white;
}
Step 4: Set up the App Component
Here, we wrap the entire app inside the ThemeProvider
, which allows the dark mode state and toggle function to be available globally.
// src/App.js
import React from 'react';
import { ThemeProvider } from './context/ThemeContext';
import ThemeToggle from './components/ThemeToggle';
import './styles.css';
function App() {
return (
<ThemeProvider>
<div className="App">
<h1>Dark Mode Toggle with Context API</h1>
<ThemeToggle />
</div>
</ThemeProvider>
);
}
export default App;
By using React's Context API, we made the dark mode state easily accessible across the app without prop-drilling. Adding localStorage ensures the theme preference persists, even after a page reload or revisit.
Feel free to tweak this basic implementation by adding more components and styles as per your needs.
If you'd like to see more of my work, check out my portfolio vrushikvisavadiya
Top comments (2)
Would it be best to use a media query to respect he users preferences?
Yes, using a media query to respect the user's preferences is also best practice.