I am attempting to recreate the theme toggle feature that the material-ui website.
My Github Repo: https://github.com/jonnyg23/flask-rest-ecommerce/tree/next-app-migration
So far, I have noticed that material-ui's website uses a cookie called paletteType in order to store the client's theme choice. I understand that a Context Provider should be used to set the cookie, however, my nav-bar implementation has an issue changing themes after the second click of my theme toggle button.
Any help would be greatly appreciated, thank you.
CustomThemeProvider.js:
import React, { createContext, useState } from "react";
import { ThemeProvider } from "@material-ui/core/styles";
import getTheme from "../themes";
import Cookie from "js-cookie";
export const CustomThemeContext = createContext({
// Set the default theme and setter.
appTheme: "light",
setTheme: null,
});
const CustomThemeProvider = ({ children, initialAppTheme }) => {
// State to hold selected theme
const [themeName, _setThemeName] = useState(initialAppTheme);
// Retrieve theme object by theme name
const theme = getTheme(themeName);
// Wrap setThemeName to store new theme names as cookie.
const setThemeName = (name) => {
// console.log("CustomThemeProvider, SetThemeName", name);
Cookie.set("appTheme", name);
_setThemeName(name);
};
const contextValue = {
appTheme: themeName,
setTheme: setThemeName,
};
return (
<CustomThemeContext.Provider value={contextValue}>
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</CustomThemeContext.Provider>
);
};
export default CustomThemeProvider;
_app.js:
import "../styles/globals.css";
import React, { useContext, useEffect } from "react";
import PropTypes from "prop-types";
import { useAuth0 } from "@auth0/auth0-react";
import Head from "next/head";
import { Provider as NextAuthProvider } from "next-auth/client";
import { makeStyles } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import Auth0ProviderWithHistory from "../auth/auth0-provider-with-history";
import CustomThemeProvider, {
CustomThemeContext,
} from "../context/CustomThemeProvider";
export default function App({ Component, pageProps }) {
// const { isLoading } = useAuth0();
const ThemeContext = useContext(CustomThemeContext);
useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<React.Fragment>
<Head>
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width"
/>
</Head>
<CustomThemeProvider initialAppTheme={ThemeContext.appTheme}>
<Auth0ProviderWithHistory>
<NextAuthProvider session={pageProps.session}>
<CssBaseline />
<Component {...pageProps} />
</NextAuthProvider>
</Auth0ProviderWithHistory>
</CustomThemeProvider>
</React.Fragment>
);
}
App.propTypes = {
Component: PropTypes.elementType.isRequired,
pageProps: PropTypes.object.isRequired,
};
ThemeModeToggle.js:
import React, { useContext } from "react";
import { IconButton } from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
import Brightness5TwoToneIcon from "@material-ui/icons/Brightness5TwoTone";
import Brightness2TwoToneIcon from "@material-ui/icons/Brightness2TwoTone";
import { CustomThemeContext } from "../context/CustomThemeProvider";
const useStyles = makeStyles((theme) => ({
light: {
color: theme.palette.secondary.main,
},
dark: {
color: theme.palette.secondary.main,
},
}));
const ThemeModeToggle = ({ fontSize }) => {
const classes = useStyles();
const { appTheme, setTheme } = useContext(CustomThemeContext);
// console.log("ThemeModeToggle", appTheme);
const handleThemeChange = (appTheme, setTheme) => {
if (appTheme === "light") {
setTheme("dark");
} else {
setTheme("light");
}
};
return (
<IconButton onClick={() => handleThemeChange(appTheme, setTheme)}>
{appTheme === "light" ? (
<Brightness5TwoToneIcon fontSize={fontSize} className={classes.light} />
) : (
<Brightness2TwoToneIcon fontSize={fontSize} className={classes.dark} />
)}
</IconButton>
);
};
export default ThemeModeToggle;