Material-UI Darkmode Toggle with User Preference Fallback

Viewed 1227

I'm attempting to create a "dark mode" toggle - which is working great. However, I would like the initial state to use the users dark/light preference.

The issue is prefersDarkMode appears to be set to false on load. It changes to true after the page fully loads (if you prefer dark mode) - but the darkState is already set to false by that point.

Is there a better way to handle this? I'm essentially looking for the same behavior that's on the https://material-ui.com/ website (user preference as the default state, with the ability to toggle dark/light mode).

Demo: https://codesandbox.io/s/dark-mode-demo-with-user-preference-fallbck-ltk09?file=/demo.js:220-807

function App() {
  const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
  const [darkMode, setDarkMode] = React.useState(prefersDarkMode);
  console.log(prefersDarkMode);

  const theme = React.useMemo(() =>
    createMuiTheme({
      palette: {
        type: darkMode ? "dark" : "light"
      }
    })
  );

  const handleDarkModeToggle = () => {
    setDarkMode(!darkMode);
  };

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <button onClick={handleDarkModeToggle}>Toggle Dark Mode</button>
    </ThemeProvider>
  );
}

export default App;
1 Answers

You can add an useEffect call, with prefersDarkMode as dependency, once this value changes the callback will be invoked Something like this,

useEffect(() => {
    setDarkMode(prefersDarkMode);
}, [prefersDarkMode]);

codesandbox link: https://sj29m.csb.app/

Related