How to Integrate Dark Mode Functionality in React Using Redux

Suzune HorikitaSuzune Horikita
3 min read

Dark mode has become a standard feature in modern web applications, enhancing user experience and reducing eye strain. In this tutorial, you'll learn how to implement a fully functional dark mode toggle in a React application using Redux for state management. We’ll cover everything from setting up the Redux store to applying conditional styling based on the selected theme. Whether you're a beginner or an experienced dev, this guide will walk you through each step with clear code examples.

Basic Required Install Commands:

npm install @reduxjs/toolkit react-redux redux-persist

Step 1: @/store/store.js – Simplified for Dark Mode Only

import { configureStore } from "@reduxjs/toolkit";
import { persistStore, persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from "redux-persist";
import storage from "redux-persist/lib/storage";
import themeReducer from "./themeSlice";

const persistConfig = {
  key: "theme",
  storage,
};

const persistedThemeReducer = persistReducer(persistConfig, themeReducer);

const store = configureStore({
  reducer: {
    theme: persistedThemeReducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }),
});

export const persistor = persistStore(store);
export default store;

step 2 :@/store/themeSlice.js

import { createSlice } from "@reduxjs/toolkit";

const themeSlice = createSlice({
  name: "theme",
  initialState: {
    isDarkMode: false,
  },
  reducers: {
    toggleDarkMode: (state) => {
      state.isDarkMode = !state.isDarkMode;
    },
  },
});

export const { toggleDarkMode } = themeSlice.actions;
export default themeSlice.reducer;

step 3 :✅ How to Use in Components

1. Wrap App with Provider and PersistGate

// index.js or main.jsx  or you can also use in layout.js if you are using next js 

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store, { persistor } from "./store/store";
import { PersistGate } from "redux-persist/integration/react";

ReactDOM.createRoot(document.getElementById("root")).render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>
);

Note that if you are using next.js, then make a Provider inside the src and wrap provider component over children at layout.js . Lastly make sure in the store.js and themeSlice.js use “use client“

//   src/Provider.js 
"use client";

import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import store, { persistor } from "./store";

export default function ReduxProvider({ children }) {
  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        {children}
      </PersistGate>
    </Provider>
  );
}

2. Toggle Dark Mode in a Component

// DarkModeToggle.jsx

import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { toggleDarkMode } from "@/store/themeSlice";

const DarkModeToggle = () => {
  const dispatch = useDispatch();
  const isDark = useSelector((state) => state.theme.isDarkMode);

  return (
    <button onClick={() => dispatch(toggleDarkMode())}>
      {isDark ? "🌙 Dark Mode ON" : "☀️ Light Mode ON"}
    </button>
  );
};

export default DarkModeToggle;

3. Apply Styles Based on Theme

// App.jsx

import React from "react";
import { useSelector } from "react-redux";
import DarkModeToggle from "./components/DarkModeToggle";

function App() {
  const isDark = useSelector((state) => state.theme.isDarkMode);

  return (
    <div className={isDark ? "dark bg-black text-white" : "bg-white text-black"}>
      <h1>Hello, World!</h1>
      <DarkModeToggle />
    </div>
  );
}

export default App;
0
Subscribe to my newsletter

Read articles from Suzune Horikita directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Suzune Horikita
Suzune Horikita