Reputation: 783
I am trying to get dark mode working in a Next.js app with MUI. The problem is that I cannot seem to get dark mode persistent once it has been set. I am setting the state with the help of createContext
since the toggle button is inside a component.
When toggling it sets the state to either true or false and sets it in the localStorage
.
However, on page refresh it goes back to a false state.
I have tried many solutions but cannot seem to get it to work.
At the moment I am doing the following within _app.js
(this is merely a snippet, full code in link):
const [darkMode, setDarkMode] = useState(false);
useEffect(() => {
const mode = localStorage.getItem("mode");
// set mode
setDarkMode(mode);
}, []);
useEffect(() => {
localStorage.setItem("mode", darkMode);
}, [darkMode]);
// Set dark mode based on media query
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
useEffect(() => {
setDarkMode(prefersDarkMode);
}, [prefersDarkMode]);
<ColorModeContext.Provider value={{ darkMode, setDarkMode }}>
<ThemeProvider theme={darkMode ? darkTheme : theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</ColorModeContext.Provider>
I have setup a CodeSandbox with the full code:
https://codesandbox.io/s/next-js-mui-dark-mode-n6l24?file=/pages/_app.js
Any help here would be appreciated!
Upvotes: 0
Views: 4639
Reputation: 21
There is an error with your csb, does not load properly. In case you want to persist dark mode and without flashing problem on MUI. Must use next-themes, easy to set up and I did follow this method https://github.com/DiMatteoL/buzzrank-tutorial and live preview https://buzzrank-tutorial.vercel.app/.
Upvotes: 0
Reputation: 6789
The third effect in your code setDarkMode(prefersDarkMode)
will overwrite the darkMode
in all cases, making any value from the local storage ineffective.
Moreover, it is better to define a custom setDarkMode
function and pass it to the ColorModeContext
provider.
// Set dark mode based on media query
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
// use the media query setting as the default (which can be overwritten)
const [darkMode, setDarkMode] = useState(prefersDarkMode);
useEffect(() => {
const mode = localStorage.getItem("mode");
// set mode
console.log(`get localStore ${mode}`);
if(mode !== null){
setDarkMode(mode === "true");
}
}, []);
// set DarkMode triggered by user
const _setDarkMode = (newmode) => {
console.log(`set localStore ${newmode}`);
localStorage.setItem("mode", newmode);
setDarkMode(newmode);
};
return (
...
<ColorModeContext.Provider
value={{ darkMode, setDarkMode: _setDarkMode }}
>
...
</ColorModeContext.Provider>
...
);
https://codesandbox.io/s/next-js-mui-dark-mode-forked-ucpvo?file=/pages/_app.js
Upvotes: 1
Reputation: 2504
As I mentioned, darkMode
should not be just false
, try to get the darkMode
from local storage first and then use it as a default value.
Here's one of my repo. https://github.com/hotcakedev628/mail-app-demo/blob/master/src/contexts/SettingsContext.js
Upvotes: 0