I have the following file theme.js
I have 3 modes dark
, classic
and light
. And I toggle the modes using the Buttons as mentioned in Home.js
file
import { createTheme } from "@mui/material";
import { createContext, useMemo, useState } from "react";
export const tokens = (mode) => ({
...(mode === "dark"
? {
// DARK MODE
primary1: {
500: "#1E2230",
},
primary2: {
500: "#171A25",
},
primary3: {
500: "#242937",
},
button: {
main: "#3555FF",
},
}
: mode === "classic"
? {
// CLASSIC MODE
primary1: {
500: "#211839",
},
primary2: {
500: "#150D29",
},
primary3: {
500: "#211839",
},
}
: // LIGHT MODE
{
primary1: {
100: "#040507",
200: "#090a0e",
300: "#0d0e15",
400: "#12131c",
500: "#161823",
600: "#45464f",
700: "#73747b",
800: "#a2a3a7",
900: "#d0d1d3",
},
primary2: {
100: "#06070a",
200: "#0c0e13",
300: "#12141d",
400: "#181b26",
500: "#1e2230",
600: "#4b4e59",
700: "#787a83",
800: "#a5a7ac",
900: "#d2d3d6",
},
primary3: {
100: "#07080b",
200: "#0e1016",
300: "#161921",
400: "#1d212c",
500: "#242937",
600: "#50545f",
700: "#7c7f87",
800: "#a7a9af",
900: "#d3d4d7",
},
}),
});
const DARK_MODE_BACKGROUND = "#131017";
// const CLASSIC_MODE_BACKGROUND = "#16121C";
const CLASSIC_MODE_BACKGROUND = "red";
const LIGHT_MODE_BACKGROUND = "white";
export const themeSettings = (mode) => {
const colors = tokens(mode);
return {
palette: {
mode: mode,
...(mode === "dark"
? {
primary: {
main: colors.primary1[500],
},
secondary: {
main: colors.primary2[500],
},
background: {
default: DARK_MODE_BACKGROUND,
},
}
: mode === "classic"
? {
primary: {
main: colors.primary1[500],
},
secondary: {
main: colors.primary2[500],
},
background: {
default: CLASSIC_MODE_BACKGROUND,
},
}
: {
primary: {
main: colors.primary1[100],
},
secondary: {
main: colors.primary2[100],
},
background: {
default: LIGHT_MODE_BACKGROUND,
},
}),
},
};
};
// context for color mode
export const ColorModeContext = createContext({
toggleColorMode: () => {},
});
export const useMode = () => {
// set the mode
const [mode, setMode] = useState("dark");
const colorMode = useMemo(
() => ({
toggleColorMode: (mode) => {
switch (mode) {
case "dark":
setMode("dark");
break;
case "classic":
setMode("classic");
break;
case "light":
default:
setMode("light");
break;
}
},
}),
[]
);
const theme = useMemo(() => createTheme(themeSettings(mode)), [mode]);
return [theme, colorMode, setMode];
};
My Issue is that when I click on Dark Button then it toggles to Dark Mode, when I click on Light then it toggles to Light Mode but When I click on Classic Button then the app breaks I don’t understand what am I doing wrong
import { Button, Typography } from "@mui/material";
import React, { useContext } from "react";
import { ColorModeContext, tokens } from "../Theme";
import { useTheme } from "@emotion/react";
export default function Home() {
const theme = useTheme();
const colors = tokens(theme.palette.mode);
const colorMode = useContext(ColorModeContext);
return (
<div>
hi
<Button
onClick={() => colorMode.toggleColorMode("dark")}
variant="contained"
>
Dark
</Button>
<Button
onClick={() => colorMode.toggleColorMode("classic")}
variant="contained"
>
Classic
</Button>
<Button
onClick={() => colorMode.toggleColorMode("light")}
variant="contained"
>
Light
</Button>
<Typography variant="h1" color="primary"></Typography>
</div>
);
}
Where am I going wrong can anyone guide through ?
The error I get in the console is
MUI: The palette mode
classic
is not supported.ERROR Cannot read properties of undefined (reading ‘primary’)
TypeError: Cannot read properties of undefined (reading ‘primary’)
at body (http://localhost:8080/main.js:3923:45)
at styles (http://localhost:8080/main.js:3952:8)
at styles (http://localhost:8080/main.js:3981:24)
at GlobalStyles.globalStyles (http://localhost:8080/main.js:5598:69)
at handleInterpolation (http://localhost:8080/main.js:1619:24)
at serializeStyles (http://localhost:8080/main.js:1733:15)
at http://localhost:8080/main.js:1229:87
at http://localhost:8080/main.js:826:12
at renderWithHooks (http://localhost:8080/main.js:32413:18)
at updateForwardRef (http://localhost:8080/main.js:35329:20)
2
Answers
MUI internally only has support for two modes ‘light’ and ‘dark’.
The error rightly suggests that behavior. "MUI: The palette mode classic is not supported."
Since you are managing the
mode
externally by yourself on yourColorModeContext
component. You could remove themode
from thepalette
object itself. Your color generation should work normally, and referencing mode should now be done fromuseMode
hook instead ofuseTheme
.After removing that, your way of getting colors should now be done with the
useMode
hooks instead ofuseTheme
you are using.On you
useMode()
hook you could also pass the current mode state.Further note, I think you should
useMode
toColorModeContext.Provider
‘svalue
.ColorModeContext.Provider
aboveThemeProvider
useMode
should now just calluseContext(ColorModeContext)
theme
you receive fromuseMode
hook to theThemeProvider
MUI provides.The logic is fine, its the steps that are all over the place.
References:
I am also facing the same issue in past and solution that work for me is to change import from @mui/material to @mui/material/styles. so what you have to do is just change you import from import { createTheme } from @mui/material to import { createTheme } from @mui/material/styles. Reason behind this is by using @mui/material/style it can handle all the issues internally.
change from
to