I set up the store like this:
store.js:
import { configureStore } from "@reduxjs/toolkit";
import { themeReducer } from "./themeSlice.js";
export default configureStore({
reducer: {
theme: themeReducer,
},
});
themeSlice.js
import { createSlice } from "@reduxjs/toolkit";
import { createTheme } from "@mui/material/styles";
import { Theme as ThemeConsts } from "../../utils/constants.js";
import * as theme from "../../utils/theme.js";
const storageTheme = theme.getLocalStorageTheme();
const mode = theme.getMediaColorScheme(storageTheme);
const themeSlice = createSlice({
name: ThemeConsts.THEME_NAME,
initialState: {
value: createTheme({
storageTheme: storageTheme,
palette: {
mode: theme.getMediaColorScheme(mode),
},
}),
},
reducers: {
systemTheme: (state) => {
let mode = ThemeConsts.DARK_THEME;
state.value.palette.mode = mode;
state.value.storageTheme = ThemeConsts.SYSTEM_THEME;
theme.setLocalStorageItem(ThemeConsts.SYSTEM_THEME);
},
lightTheme: (state) => {
state.value.palette.mode = ThemeConsts.LIGHT_THEME;
state.value.storageTheme = ThemeConsts.LIGHT_THEME;
theme.setLocalStorageItem(ThemeConsts.LIGHT_THEME);
},
darkTheme: (state) => {
state.value.palette.mode = ThemeConsts.DARK_THEME;
state.value.storageTheme = ThemeConsts.DARK_THEME;
theme.setLocalStorageItem(ThemeConsts.DARK_THEME);
},
},
});
export const { systemTheme, lightTheme, darkTheme } = themeSlice.actions;
export const themeReducer = themeSlice.reducer;
SelectTheme.jsx
import { useSelector, useDispatch } from "react-redux";
import { systemTheme, lightTheme, darkTheme } from "../store/themeSlice.js";
import { Theme as ThemeConsts } from "../../utils/constants.js";
import { FormControl, InputLabel, MenuItem, Select } from "@mui/material";
function SelectTheme() {
const dispatch = useDispatch();
const themeSelector = useSelector((state) => state.theme.value);
const options = [
{ tag: ThemeConsts.SYSTEM_THEME, label: "System" },
{ tag: ThemeConsts.LIGHT_THEME, label: "Light" },
{ tag: ThemeConsts.DARK_THEME, label: "Dark" },
];
const handleChangeSelectMode = (event) => {
switch (event.target.value) {
case ThemeConsts.LIGHT_THEME:
dispatch(lightTheme());
break;
case ThemeConsts.DARK_THEME:
dispatch(darkTheme());
break;
default:
dispatch(systemTheme());
break;
}
};
return (
<>
<FormControl fullWidth>
<InputLabel id="input-label-mode">Mode</InputLabel>
<Select
labelId="input-label-mode"
id="select-mode"
label="Mode"
onChange={handleChangeSelectMode}
value={themeSelector.storageTheme}
>
{options.map((option, index) => (
<MenuItem key={index} value={option.tag}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
</>
);
}
export default SelectTheme;
Everything works, the property is stored and read on the local storage, when there is a page refresh the theme actually changes and the select points to the correct theme.
Only problem is when there is the handleChangeSelectMode event, it doesn’t change my theme dinamically (to change it I have to reload the page).
And this message comes up in console:
enter image description here
Pasquale Carrotta is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.