React  

Dark Mode Toggle in React with Context API

βš›οΈ Introduction

Dark mode has become a must-have feature in modern web apps πŸŒ‘.

It’s not just about style β€” it improves accessibility, reduces eye strain, and adds a sleek aesthetic to your app ✨.

In this article, we’ll build a Dark Mode Toggle feature in React using the Context API, so that theme changes are shared across your entire app β€” easily and efficiently! ⚑

🧠 Why Use Context API for Dark Mode?

Normally, you can manage theme toggles with useState, but if you have multiple components that need to know the theme (like Navbar, Footer, Cards, etc.), passing props everywhere becomes messy. 😩

That’s where React’s Context API comes in!

It lets you:

  • Share theme state across components 🌍

  • Avoid prop drilling πŸ”

  • Keep your code clean and scalable πŸ’‘

πŸ—οΈ Step 1. Set up a React App

If you don’t already have a React app, create one:

npx create-react-app dark-mode-toggle

cd dark-mode-toggle

npm start

Now, you’re ready to build the dark mode feature! πŸš€

βš™οΈ Step 2. Create a Theme Context

Inside your src folder, create a new file:

πŸ“ ThemeContext.js

import { createContext, useState, useContext } from "react";

// Step 1: Create the context

const ThemeContext = createContext();



// Step 2: Create a provider component

export function ThemeProvider({ children }) {

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



const toggleTheme = () => {

setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));

};



return (

<ThemeContext.Provider value={{ theme, toggleTheme }}>

{children}

</ThemeContext.Provider>

);

}



// Step 3: Custom hook to use the Theme Context easily

export function useTheme() {

return useContext(ThemeContext);

}

βœ… Explanation

  • ThemeContext holds our theme state (light or dark)

  • ThemeProvider wraps our entire app and provides theme info

  • toggleTheme switches between light and dark modes

  • useTheme() is a helper hook for easy access

🌈 Step 3. Wrap Your App with ThemeProvider

Now open index.js (or main.jsx if using Vite) and wrap your app inside the ThemeProvider.

import React from "react";

import ReactDOM from "react-dom/client";

import App from "./App";

import { ThemeProvider } from "./ThemeContext";

import "./index.css";



const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(

<ThemeProvider>

<App />

</ThemeProvider>

);

🎯 This ensures that every component in your app can access the theme context.

πŸ’‘ Step 4. Create a Toggle Button Component

Now let’s create a button to switch between dark and light themes.

πŸ“ ThemeToggle.js

import React from "react";

import { useTheme } from "./ThemeContext";



function ThemeToggle() {

const { theme, toggleTheme } = useTheme();



return (

<button

onClick={toggleTheme}

style={{

padding: "10px 20px",

borderRadius: "10px",

border: "none",

cursor: "pointer",

backgroundColor: theme === "light" ? "#333" : "#fff",

color: theme === "light" ? "#fff" : "#333",

transition: "all 0.3s ease",

}}

>

{theme === "light" ? "πŸŒ™ Dark Mode" : "β˜€οΈ Light Mode"}

</button>

);

}



export default ThemeToggle;

🧠 Explanation

  • We use the useTheme() hook to access the theme and toggleTheme

  • Button style changes dynamically based on the current theme

  • Emoji icons πŸŒ™β˜€οΈ make it fun and intuitive

πŸ–₯️ Step 5. Apply the Theme to the App

Let’s make our app background and text color change with the theme.

App.js πŸ‘‡

import React from "react";

import { useTheme } from "./ThemeContext";

import ThemeToggle from "./ThemeToggle";



function App() {

const { theme } = useTheme();



const appStyles = {

backgroundColor: theme === "light" ? "#f9f9f9" : "#121212",

color: theme === "light" ? "#000" : "#fff",

minHeight: "100vh",

display: "flex",

flexDirection: "column",

alignItems: "center",

justifyContent: "center",

transition: "all 0.3s ease-in-out",

};



return (

<div style={appStyles}>

<h1>React Dark Mode with Context API πŸŒ™β˜€οΈ</h1>

<p>Switch between themes easily using Context!</p>

<ThemeToggle />

</div>

);

}



export default App;

🧠 Step 6: How It Works

When you click the toggle button:

  1. toggleTheme() updates the state inside ThemeProvider.

  2. The new theme value (light or dark) is passed through Context.

  3. ll components using useTheme() automatically re-render and apply the new styles.

πŸŽ‰ Boom! Your entire app now switches themes smoothly.

πŸŒ™ Step 7 (Optional): Persist Theme in Local Storage

To remember the user’s theme preference after page reloads, you can save it in localStorage.

Modify ThemeProvider like this πŸ‘‡

import { createContext, useState, useEffect, useContext } from "react";



const ThemeContext = createContext();



export function ThemeProvider({ children }) {

const [theme, setTheme] = useState(() => {

return localStorage.getItem("theme") || "light";

});



useEffect(() => {

localStorage.setItem("theme", theme);

}, [theme]);



const toggleTheme = () => {

setTheme((prev) => (prev === "light" ? "dark" : "light"));

};



return (

<ThemeContext.Provider value={{ theme, toggleTheme }}>

{children}

</ThemeContext.Provider>

);

}



export function useTheme() {

return useContext(ThemeContext);

}

βœ… Now the theme stays even after page refresh πŸ”

🧩 Step 8. (Bonus) Add CSS Transitions or Tailwind Support

If you’re using Tailwind CSS, you can easily integrate dark mode by toggling the dark class on the <html> element.

Example

useEffect(() => {

document.documentElement.classList.toggle("dark", theme === "dark");

}, [theme]);

Then, in Tailwind config, enable dark mode:

module.exports = {

darkMode: "class",

// ...

};

Now, your entire UI will follow the theme dynamically ✨

πŸ’« Benefits of Using Context API for Dark Mode

Feature: Why It Helps

  • πŸ”„ Global Access All components share the same theme

  • 🧠 Clean Code No prop drilling

  • ⚑ Performance React only re-renders components that use context

  • πŸ’Ύ Persistent Easily save user preferences

  • 🎨 Flexible Works with CSS, Tailwind, or Styled Components

πŸš€ Final Output

🌞 Light Mode

πŸ–€ Dark Mode

Switch smoothly with one click, and your app remembers the choice!

🧠 Conclusion

With just a few lines of code, you built a fully functional Dark Mode toggle using React’s Context API. πŸŽ‰

You learned how to:

  • Use Context API for global theme state 🌍

  • Toggle between light and dark themes dynamically πŸŒ—

  • Persist theme preferences with localStorage πŸ’Ύ

This pattern is reusable for any global state β€” not just themes, but also language, authentication, or user preferences. ⚑

So next time someone asks how to implement dark mode β€”

you’ll say, β€œEasy β€” React + Context API!” πŸŒ™β˜€οΈ