'ReactJS/MUI (v5.6.2) Dark mode toggle not updating state

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?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source