react Advanced

React Dark Mode hook

React Dark Mode hook
React Dark Mode Hook

Open this example in our interactive code editor to experiment with it.

Try the Editor

Switch 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 isDarkMode changes, syncing the value to localStorage and toggling a dark-mode CSS class on document.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 isDarkMode and toggle from the custom hook.
  • A conditional class name and heading text reflect the current theme.
  • The button calls toggle on 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 localStorage ensures the user’s preference survives page refreshes and new sessions.
  • The useEffect hook keeps the DOM in sync with the React state, applying or removing the dark-mode class on the body element.

Try this in our interactive code editor

Practice hands-on with our built-in code sandbox.

Open Code Editor
Adrian Bigaj
Adrian Bigaj

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.