I followed many solutions like this https://stackoverflow.com/a/71081567/19460332 and the official solution for this https://github.com/mui/material-ui/blob/master/examples/nextjs but nothing worked for me. I am using nextjs , material ui and js-cookies
the issue I am facing is for the MUI Switch
have a look to my code here https://github.com/MaheshYadavGitHub/pizza-gallery:
Here is the code for the section that is breaking :
below is the Layout.js where the Switch to toggle darkMode is not working as expected. The darkTheme gets applied as it gets from the cookies but the switch button still stays in off position on the first render but after another render it works perfectly and when again manually refreshed it does the same behaviour :-
import { useState, useContext } from "react";
import {
Container,
AppBar,
Toolbar,
Typography,
Link,
Switch,
CssBaseline,
ThemeProvider,
createTheme,
} from "@material-ui/core";
import { red } from "@material-ui/core/colors";
import Head from "next/head";
import Image from "next/image";
import NextLink from "next/link";
import useStyles from "../utils/styles";
import { Store } from "../utils/Store";
import Cookies from "js-cookie";
const Layout = ({ title, children }) => {
const { state, dispatch } = useContext(Store);
const { darkMode } = state;
const classes = useStyles();
const theme = createTheme({
palette: {
type: darkMode ? "dark" : "light",
primary: {
main: "#556cd6",
},
secondary: {
main: "#19857b",
},
error: {
main: red.A400,
},
},
typography: {
fontFamily: ["Arial", "Roboto Condensed"].join(","),
fontWeight: 700,
h1: {
fontSize: "1.6rem",
margin: "1rem 0rem",
fontWeight: 600,
"@media (min-width:600px)": {
fontSize: "2.6rem",
},
},
h6: {
fontWeight: 700,
},
navLinks: {
color: "#fff",
},
},
});
const handleThemeChange = (event) => {
dispatch({ type: darkMode ? "DARK_MODE_OFF" : "DARK_MODE_ON" });
const newThemeMode = !darkMode;
Cookies.set("darkMode", newThemeMode ? "ON" : "OFF");
};
return (
<>
<Head>
<title>{title ? `${title} - Pizza Gallery` : "Pizza Gallery"}</title>
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
<AppBar position="static" className={classes.navbar}>
<Toolbar>
<NextLink href="/" passHref>
<Link>
<Typography
variant="h6"
className={classes.brand}
component="div"
>
Pizza Gallery
</Typography>
</Link>
</NextLink>
<div className={classes.grow}></div>
<Switch
id="switch"
checked={darkMode}
onChange={handleThemeChange}
color="primary"
></Switch>
<NextLink href="/login" passHref>
<Link>
<Typography>Login</Typography>
</Link>
</NextLink>
<NextLink href="/cart" passHref>
<Link>
<Typography>Cart</Typography>
</Link>
</NextLink>
</Toolbar>
</AppBar>
<Container className={classes.main}>{children}</Container>
<footer className={classes.footer}>
<Typography>all rights reserved © pizza gallery 2022</Typography>
</footer>
</ThemeProvider>
</>
);
};
export default Layout;
below is the Store :-
import Cookies from "js-cookie";
import { createContext, useReducer } from "react";
export const Store = createContext();
const initialState = {
darkMode: Cookies.get("darkMode") === "ON" ? true : false,
};
const reducer = (state, action) => {
switch (action.type) {
case "DARK_MODE_ON":
return { ...state, darkMode: true };
case "DARK_MODE_OFF":
return { ...state, darkMode: false };
default:
return state;
}
};
export const StoreProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
const value = { state, dispatch };
return <Store.Provider value={value}>{children}</Store.Provider>;
};
/pages/_app.js
import { useEffect } from "react";
import "../styles/globals.css";
import { StoreProvider } from "../utils/Store";
function MyApp({ Component, pageProps }) {
useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<StoreProvider>
<Component {...pageProps} />
</StoreProvider>
);
}
export default MyApp;
/pages/_document.js
import { ServerStyleSheets } from "@material-ui/core/styles";
import Document, { Html, Head, Main, NextScript } from "next/document";
import React from "react";
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head></Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
MyDocument.getInitialProps = async (ctx) => {
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () => {
return originalRenderPage({
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
});
};
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: [
...React.Children.toArray(initialProps.styles),
sheets.getStyleElement(),
],
};
};