React  

How to Implement Dark Mode Toggle in React

Introduction

Dark mode has become a standard feature in modern web applications. Users prefer it for better readability, reduced eye strain, and improved battery performance on devices.

If you are building a modern UI, implementing a dark mode toggle in React is almost expected. The good news is that it is not complex if approached step by step with a clean structure.

In this guide, we will learn how to implement a dark mode toggle in React using state management, CSS variables, and persistent storage. This approach is widely used in React applications, UI/UX design systems, and modern frontend development.

What is Dark Mode in React?

Dark mode is a UI feature that switches the application theme from light colors to darker colors.

Instead of redesigning everything, we dynamically change styles based on a theme state.

Why Dark Mode is Important

  • Improves user experience

  • Reduces eye strain in low light

  • Saves battery on OLED screens

  • Enhances modern UI design

How Dark Mode Works Internally

At a high level, dark mode works by:

  • Storing the current theme (light or dark)

  • Applying styles based on that theme

  • Updating UI when the theme changes

In React, this is typically handled using state and CSS.

Step 1: Create a React Project

npx create-react-app dark-mode-app
cd dark-mode-app
npm start

Explanation

  • Creates a new React application

  • Starts development server

  • Provides base setup for UI implementation

Step 2: Create Theme State

Inside your main component (App.js):

import { useState } from "react";

function App() {
  const [theme, setTheme] = useState("light");

  return (
    <div>
      <h1>Dark Mode Example</h1>
    </div>
  );
}

export default App;

Explanation

  • theme stores current mode (light or dark)

  • setTheme updates the mode

  • Default theme is light

Step 3: Create Toggle Function

const toggleTheme = () => {
  setTheme(theme === "light" ? "dark" : "light");
};

Explanation

  • Checks current theme

  • Switches between light and dark

  • Triggers UI re-render automatically

Step 4: Apply Theme Class to Root

return (
  <div className={theme}>
    <button onClick={toggleTheme}>Toggle Theme</button>
    <h1>Dark Mode Example</h1>
  </div>
);

Explanation

  • Adds class based on current theme

  • CSS will control appearance

  • Button triggers theme change

Step 5: Define CSS for Themes

Create styles in App.css:

.light {
  background-color: white;
  color: black;
}

.dark {
  background-color: #121212;
  color: white;
}

Explanation

  • .light defines light theme styles

  • .dark defines dark theme styles

  • React switches class dynamically

Step 6: Use CSS Variables (Better Approach)

:root {
  --bg-color: white;
  --text-color: black;
}

.dark {
  --bg-color: #121212;
  --text-color: white;
}

body {
  background-color: var(--bg-color);
  color: var(--text-color);
}

Explanation

  • CSS variables allow flexible theming

  • Only variables change, not full styles

  • Easier to maintain for large apps

Step 7: Persist Theme Using Local Storage

import { useEffect } from "react";

useEffect(() => {
  const savedTheme = localStorage.getItem("theme");
  if (savedTheme) {
    setTheme(savedTheme);
  }
}, []);

useEffect(() => {
  localStorage.setItem("theme", theme);
}, [theme]);

Explanation

  • Loads saved theme on page load

  • Stores theme when changed

  • Keeps user preference persistent

Step 8: Improve UX with Default System Preference

useEffect(() => {
  const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
  setTheme(prefersDark ? "dark" : "light");
}, []);

Explanation

  • Detects system theme

  • Applies default theme automatically

  • Improves user experience

Complete Example

import { useState, useEffect } from "react";
import "./App.css";

function App() {
  const [theme, setTheme] = useState("light");

  useEffect(() => {
    const savedTheme = localStorage.getItem("theme");
    if (savedTheme) {
      setTheme(savedTheme);
    }
  }, []);

  useEffect(() => {
    localStorage.setItem("theme", theme);
  }, [theme]);

  const toggleTheme = () => {
    setTheme(theme === "light" ? "dark" : "light");
  };

  return (
    <div className={theme}>
      <button onClick={toggleTheme}>Toggle Theme</button>
      <h1>Dark Mode in React</h1>
    </div>
  );
}

export default App;

Real-World Use Case

Many modern applications like dashboards, SaaS platforms, and developer tools implement dark mode to enhance usability.

Example scenarios:

  • Admin dashboards used at night

  • Developer tools with long screen usage

  • Mobile apps with battery optimization

Best Practices for Dark Mode in React

Use CSS Variables

Helps manage themes easily across components.

Avoid Hardcoding Colors

Always use variables for flexibility.

Maintain Accessibility

Ensure good contrast between text and background.

Test Across Devices

Check behavior on mobile and desktop.

Common Mistakes

Not Saving Theme

Leads to poor user experience.

Overusing Inline Styles

Makes code hard to maintain.

Ignoring System Preferences

Misses better UX opportunities.

Advantages of Dark Mode

  • Better readability in low light

  • Improved user experience

  • Modern UI appeal

Limitations

  • Needs proper design handling

  • Poor contrast can affect readability

Summary

Implementing a dark mode toggle in React is a practical and essential feature for modern web applications. By using React state, CSS variables, and local storage, developers can create a seamless and user-friendly theme-switching experience. With proper implementation, dark mode enhances usability, improves accessibility, and aligns with modern UI/UX trends, making it a valuable addition to any React application.