React Dark Mode hook
Open this example in our interactive code editor to experiment with it.
Try the EditorSwitch themes
import { useEffect, useState } from "react";
const useDarkMode = () => {
const [isDarkMode, setIsDarkMode] = useState(
() => localStorage.getItem("darkMode") === "true"
);
const toggle = () => setIsDarkMode((prev) => !prev);
useEffect(() => {
localStorage.setItem("darkMode", isDarkMode);
if (isDarkMode) {
document.body.classList.add("dark-mode");
} else {
document.body.classList.remove("dark-mode");
}
}, [isDarkMode]);
return { isDarkMode, toggle };
};
export default useDarkMode;
- useState is initialized with a lazy initializer that reads from
localStorage, so the theme preference persists across page reloads. - toggle flips the boolean state using the functional updater
(prev) => !prev. - useEffect runs whenever
isDarkModechanges, syncing the value tolocalStorageand toggling adark-modeCSS class ondocument.body.
import useDarkMode from "./useDarkMode";
export default function App() {
const { isDarkMode, toggle } = useDarkMode();
return (
<div className={isDarkMode ? "dark" : "light"}>
<h1>{isDarkMode ? "Dark Mode" : "Light Mode"}</h1>
<button onClick={toggle}>
Switch to {isDarkMode ? "Light" : "Dark"} Mode
</button>
</div>
);
}
- The App component destructures
isDarkModeandtogglefrom the custom hook. - A conditional class name and heading text reflect the current theme.
- The button calls
toggleon click to switch between light and dark modes.
Summary
- useDarkMode encapsulates all dark mode logic: state management, persistence via
localStorage, and DOM class toggling. - The hook is reusable across any component or project that needs theme switching.
- Using
localStorageensures the user’s preference survives page refreshes and new sessions. - The
useEffecthook keeps the DOM in sync with the React state, applying or removing thedark-modeclass on the body element.
Try this in our interactive code editor
Practice hands-on with our built-in code sandbox.
Open Code Editor
Creator of BigDevSoon
Full-stack developer and educator passionate about helping developers build real-world skills through hands-on projects. Creator of BigDevSoon, a vibe coding platform with 21 projects, 100 coding challenges, 40+ practice problems, and Merlin AI.
Related Pills
React fetch hook
Let's create a custom hook for fetching data with the browser fetch.
Event handlers arguments in React
onClick, onChange, onBlur... We usually pass a reference to the function handler but how do we add more arguments instead of just the event itself?
React counter hook
Let's create a custom hook for tracking the counter state and exposing the current counter value with increment, decrement handlers.