Dark mode is no longer an optional feature for modern web applications; it is an industry standard. However, implementing it poorly can result in the dreaded “flash of light mode”—where the screen briefly blasts the user with a white background on every page refresh before the dark theme kicks in.
To build a seamless experience, you need to manage the theme state and persist the user’s preference in the browser’s local storage. This custom React hook handles all of that logic for you in one clean package.
The useDarkMode Hook
Create a file named useDarkMode.js in your hooks folder. This hook checks if the user has a saved preference first. If they don’t, it defaults to a light theme. It then automatically applies a “dark” class to the root HTML body element so your CSS can take over.
import { useState, useEffect } from 'react';
const useDarkMode = () => {
// Check local storage for a saved theme, default to 'light'
const [theme, setTheme] = useState(() => {
try {
const savedTheme = window.localStorage.getItem('theme');
return savedTheme ? savedTheme : 'light';
} catch (error) {
return 'light';
}
});
useEffect(() => {
// Apply the theme class to the root body element
const root = window.document.documentElement;
if (theme === 'dark') {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
// Save the current preference to local storage
window.localStorage.setItem('theme', theme);
}, [theme]);
// Function to toggle between modes
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
};
return [theme, toggleTheme];
};
export default useDarkMode;
How to Use It
To implement this in your application, simply import the hook into your navigation bar or layout component and attach the toggle function to a button.
import React from 'react';
import useDarkMode from './hooks/useDarkMode';
const ThemeToggle = () => {
const [theme, toggleTheme] = useDarkMode();
return (
<button
onClick={toggleTheme}
className="theme-toggle-btn"
aria-label="Toggle Dark Mode"
>
{theme === 'light' ? '🌙 Switch to Dark' : '☀️ Switch to Light'}
</button>
);
};
export default ThemeToggle;
Styling the Theme
Once this hook is active, all you need to do is write your CSS using the .dark class selector to override your standard light-mode colors. If you are using Tailwind CSS, this integrates perfectly with their standard dark mode configuration!