I am trying to wrap my mind around this and find the breaking point for all morning but am not able to. I have only followed the official docs until now.
I need to update the theme from dark to light in a React App but the state wont change (or resets immediately)
Heres my code:
App.tsx
import React, { createContext, useMemo, useState } from 'react';
import styles from './App.module.scss';
import {createTheme,CssBaseline,PaletteMode,responsiveFontSizes,ThemeProvider,
useMediaQuery} from '@mui/material';
import { getDefaultThemeMode } from './shared/theme/default-theme-mode';
import { getDesignTokens } from './shared/theme/mui-design-tokens';
import Main from './main/Main';
import { Navigate, Route, Routes } from 'react-router-dom';
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import { OPTIONS } from './shared/i18n/translations';
export const ColorModeContext = React.createContext({
toggleColorMode: () => { },
});
function App() {
// THEME
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const [mode, setMode] = React.useState<'light' | 'dark'>('light');
React.useEffect(() => {
setMode(prefersDarkMode ? 'dark' : 'light');
}, [prefersDarkMode]);
const colorMode = React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
},
}),
[]
);
let theme = React.useMemo(
() =>
createTheme(getDesignTokens(mode)),
[mode]
);
theme = responsiveFontSizes(theme);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<div className={styles.app} style={{background: theme.palette.background.default}}>
<CssBaseline/>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"/>
<Routes>
<Route path='/home' element={<Main/>}/>
<Route path='*' element={<Navigate to='home'/>}/>
</Routes>
</div>
</ThemeProvider>
</ColorModeContext.Provider>
);
}
export default App;
getDesignTokens Function:
const getDesignTokens = (mode: PaletteMode): ThemeOptions => ({
palette: {
mode,
...(mode === 'light' ? {
primary: {
main: '#3c3c3c',
},
} : {
primary: {
main: '#3c3c3c',
},
})
}});
And finally, I am trying to update the theme from outside the App.tsx component this way:
const ThemeToggle = () => {
const theme = useTheme();
const colorMode = useContext(ColorModeContext);
return (
<>
<label htmlFor='theme-toggle' className={`${styles.toggleBtn}
${theme.palette.mode === 'dark' ? styles.dark : ''}`}
onClick={colorMode.toggleColorMode}>
<input type='checkbox' id='theme-toggle' className={styles.input}/>
</label>
</>
)
}
export default ThemeToggle;
I must be missing something obvious but have tried everything. Anyone has done something similar?