🌞 Toggle theme 🌑 in React with MUI v5 and Redux 🚀
Rajesh Joshi

Rajesh Joshi @rajeshj3

About: 👨‍💻 Senior Software Engineer Specialized in Scalable Backend Solutions | Redis Hackathon Global Winner 🏆 | Microservices | Data Pipelines

Location:
India
Joined:
Dec 24, 2019

🌞 Toggle theme 🌑 in React with MUI v5 and Redux 🚀

Publish Date: Jan 9 '22
47 8

Dark and Light theme in any Web-App make it even more attractive. To build a theme enabled web-app in ReactJS with the help of Material-UI v5 and Redux follow this article.


Theme Animation


Directory Structure

src
│   App.js
│   index.css
│   index.js
│
└───theme
│   │   theme.js
│
└───redux
│   │   store.js
│   │
│   └───theme
│       │   themeSlice.js
Enter fullscreen mode Exit fullscreen mode

Create a React Project

Using npx create a new react project.

$ npx create-react-app my-site
Enter fullscreen mode Exit fullscreen mode

Add dependencies

Add the following libraries

$ yarn add @reduxjs/toolkit react-redux @mui/material @emotion/react @emotion/styled
Enter fullscreen mode Exit fullscreen mode

your package.json should look like this

{
  "name": "my-site",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@emotion/react": "^11.7.1",
    "@emotion/styled": "^11.6.0",
    "@mui/material": "^5.2.7",
    "@reduxjs/toolkit": "^1.7.1",
    "@testing-library/jest-dom": "^5.16.1",
    "@testing-library/react": "^12.1.2",
    "@testing-library/user-event": "^13.5.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-redux": "^7.2.6",
    "react-scripts": "5.0.0",
    "web-vitals": "^2.1.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": ["react-app", "react-app/jest"]
  },
  "browserslist": {
    "production": [">0.2%", "not dead", "not op_mini all"],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Let's Write Code 🚀

Start with Writing Store / Redux

To learn the basics of the new Redux using a simple Counter App, you may have a look at my recent article New Redux 😱 is just 🔥.

Create themeSlice.js

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

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

export const { toggleTheme } = themeSlice.actions;

export default themeSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

In initialState the default value of darkTheme is false, i.e. by default the theme will be light.

Register the themeSlice in store. So, your store.js should look like this.

import { configureStore } from "@reduxjs/toolkit";
import theme from "./theme/themeSlice";

export default configureStore({
  reducer: {
    theme,
  },
});
Enter fullscreen mode Exit fullscreen mode

Don't forget to provide the store to the App in index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import "./index.css";

// redux
import store from "./redux/store";
import { Provider } from "react-redux";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

Let's write theme/theme.js

Define both light and dark themes in theme.js

import { createTheme } from "@mui/material";

export const lightTheme = createTheme({
  palette: {
    mode: "light",
    background: {
      paper: "#f2f2f2",
    },
    text: {
      primary: "#11111",
    },
  },
});

export const darkTheme = createTheme({
  palette: {
    mode: "dark",
    background: {
      paper: "#222",
    },
    text: {
      primary: "#fff",
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Write App.js

Based on the Global state variable darkTheme, provide theme to ThemeProvider HOC.

import { useSelector, useDispatch } from "react-redux";
import { ThemeProvider } from "@mui/material/styles";
import {
  Paper,
  FormGroup,
  FormControlLabel,
  Switch,
  Typography,
} from "@mui/material";

import { darkTheme, lightTheme } from "./theme/theme";
import { toggleTheme } from "./redux/theme/themeSlice";

export default function App() {
  // get theme from store
  const theme = useSelector((state) => state.theme);

  // initialize dispatch variable
  const dispatch = useDispatch();

  // ToggleSwitch component
  const ToggleSwitch = () => {
    return (
      <div
        style={{
          position: "absolute",
          top: "10px",
          right: "10px",
        }}
      >
        <FormGroup>
          <FormControlLabel
            control={
              <Switch
                checked={theme.darkTheme}
                onChange={() => dispatch(toggleTheme())}
              />
            }
            label="Toggle Theme"
          />
        </FormGroup>
      </div>
    );
  };

  return (
    <ThemeProvider theme={theme.darkTheme ? darkTheme : lightTheme}>
      <Paper
        style={{
          minHeight: "100vh",
          borderRadius: "0",
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          justifyContent: "center",
        }}
      >
        <ToggleSwitch />
        <Typography variant="h1">Hello</Typography>
      </Paper>
    </ThemeProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Run the Development Server 🚀

$ yarn start
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3000

Light Theme

Light Theme

Dark Theme

Dark Theme


Hurray! You just learned 🌞 Toggle theme 🌑 in React with MUI v5 and Redux 🚀


I hope, you guys liked this quick tutorial. If so, then please don't forget to drop a Like ❤️

And also, help me reach 1k Subscribers 🤩, on my YouTube channel.

Happy Coding! 😃💻

Comments 8 total

  • Harshita Arya
    Harshita AryaJan 9, 2022

    Thanks, this is really helpful🔥

  • Raí B. Toffoletto
    Raí B. ToffolettoJan 10, 2022

    A custom hook useTheme would be probably easier 😉

    • tim.rohrer
      tim.rohrerFeb 24, 2022

      Do you have a link to an article describing this approach?

      • Raí B. Toffoletto
        Raí B. ToffolettoMar 2, 2022

        Not from the top of my head, but look for hooks and context.
        The idea is to create a provider that will create the theme and hold the state with a method for toggling it. with that like redux, it can be called from any sub component.

        For me looks like a cleaner way than setting up a redux store.

      • Ashutosh Khanduala
        Ashutosh KhandualaApr 9, 2022

        create your custom useTheme hook: youtu.be/5LrDIWkK_Bc

  • Ali Eslam
    Ali EslamMar 19, 2022

    Thank you!

  • hhelsinki
    hhelsinkiMay 3, 2023

    Good describe, nice example. 🤩️

Add comment