How to add dual theme to your React App ?

Dual Themes are very common nowadays in websites most commonly the light and dark versions and more and more apps and websites are including this feature. For React apps, the Material UI framework provides very useful functions using multiple themes, and switching between them is quite easy. In this article we will create a simple react app and switch between Dark and Light themes using a Switch component.

Prerequisites

Steps to create React Application And Installing Module:

Step 1: Create a React application using the following command:

npx create-react-app gfg

Step 2: After creating your project folder i.e. gfg, move to it using the following command:

cd gfg

Step 3: After creating the ReactJS application, Install the material-ui modules using the following command:

npm install @material-ui/core

Project Structure:

Example: Demonstrating dual theme in react app.

Javascript




// theme.js
 
import { createMuiTheme, responsiveFontSizes } from "@material-ui/core/styles";
 
const lightTheme = responsiveFontSizes(
    createMuiTheme({
        spacing: 4,
        typography: {
            fontFamily: ["Roboto", "Raleway", "Open Sans"].join(","),
            h1: {
                fontSize: "5rem",
                fontFamily: "Raleway",
            },
            h3: {
                fontSize: "2.5rem",
                fontFamily: "Open Sans",
            },
        },
        palette: {
            background: {
                default: "#009900", //green
            },
            primary: {
                main: "#009900", //green
            },
            secondary: {
                main: "#000000", //black
                icons: "#009900", //white
            },
            text: {
                primary: "#000000", //black
                secondary: "#FFFFFF", //white
            },
        },
    })
);
 
const darkTheme = responsiveFontSizes(
    createMuiTheme({
        spacing: 4,
        typography: {
            fontFamily: ["Roboto", "Raleway", "Open Sans"].join(","),
            h1: {
                fontSize: "5rem",
                fontFamily: "Raleway",
            },
            h3: {
                fontSize: "2.5rem",
                fontFamily: "Open Sans",
            },
        },
        palette: {
            background: {
                default: "#000000", //black
            },
            primary: {
                main: "#FFFFFF", //white
            },
            secondary: {
                main: "#FFFFFF", //white
                icons: "#FFFFFF", //white
            },
            text: {
                primary: "#FFFFFF", //white
                secondary: "#FFFFFF", //white
            },
        },
    })
);
 
export default lightTheme;
export { darkTheme };


Javascript




// App.js
 
import React, { Component } from "react";
import "./App.css";
import CssBaseline from "@material-ui/core/CssBaseline";
import { ThemeProvider } from "@material-ui/styles";
import { createMuiTheme } from "@material-ui/core/styles";
import Container from "@material-ui/core/Container";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
import { AppBar, Toolbar } from "@material-ui/core";
import Switch from "@material-ui/core/Switch";
import lightTheme, { darkTheme } from "./theme";
import Grid from "@material-ui/core/Grid";
import Component1 from "./Component1";
 
function App() {
    // The 'checked' state is for the status of Switch component
    const [checked, setChecked] = React.useState(false);
    // The 'newtheme' state tells if the new theme (i.e, dark theme)
    // is to be applied or not.
    const [newtheme, setTheme] = React.useState(false);
    function changeTheme() {
        setTheme(!newtheme);
        setChecked(!checked);
    }
    // Conditional - if newtheme is set to true
    // then set appliedTheme to dark
    const appliedTheme = createMuiTheme(newtheme ? darkTheme : lightTheme);
    return (
        <React.Fragment>
            <ThemeProvider theme={appliedTheme}>
                <CssBaseline />
                <AppBar position="static" color="transparent" elevation={0}>
                    <Toolbar>
                        {/* Switch position whenever
                changed triggers the changeTheme() */}
                        <Switch
                            checked={checked}
                            onChange={() => {
                                changeTheme();
                            }}
                            style={{
                                color: appliedTheme.palette.secondary.icons,
                            }}
                        />
                    </Toolbar>
                </AppBar>
                <Container maxWidth="sm">
                    <Typography
                        component="h1"
                        variant="h1"
                        align="center"
                        color="textPrimary"
                        gutterBottom
                    >
                        Beginner for Beginner
                    </Typography>
                    <br />
                    <Component1></Component1>
                    <br />
                    <Grid
                        container
                        direction="row"
                        justify="center"
                        spacing={4}
                    >
                        <Grid item>
                            <Button variant="contained" color="secondary">
                                Button 1
                            </Button>
                        </Grid>
                        <Grid item>
                            <Button variant="outlined" color="secondary">
                                Button 2
                            </Button>
                        </Grid>
                    </Grid>
                    <br />
                </Container>
            </ThemeProvider>
        </React.Fragment>
    );
}
 
export default App;


Javascript




// Component1.js
 
import React, { Component } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { useTheme } from "@material-ui/core/styles";
import Typography from "@material-ui/core/Typography";
 
const useStyles = makeStyles((theme) => ({
    root: {
        flexGrow: 1,
    },
}));
 
export default function Component1() {
    const theme = useTheme();
    const classes = useStyles(theme);
    return (
        <div className={classes.root}>
            <Typography
                variant="h3"
                align="center"
                color="textPrimary"
                paragraph
            >
                This is a Child Component text.
            </Typography>
        </div>
    );
}


Step to Run Application: Run the application using the following command from the root directory of the project:

npm start

Output: Now open your browser and go to http://localhost:3000/, you will see the following output: