Toggling between dark/light mode Material UI

Viewed 2161

I just can't figure it out. I want to change background with Switch, but it works only the first time, doesn't work on subsequent clicks. Here is code sandbox:

https://codesandbox.io/s/strange-shaw-2tfk5

Could someone enlighten me what is going on? I'm using Material UI with React

minimal reproducible example: this is my App component

import React from "react";
import { useState } from "react";
import { ThemeProvider, createTheme } from "@material-ui/core/styles";
import { Container, Switch, CssBaseline } from "@material-ui/core";

const darkTheme = createTheme({
  palette: {
    type: "dark",
    background: {
      default: "hsl(230, 17%, 14%)"
    }
  }
});

const lightTheme = createTheme({
  palette: {
    type: "light",
    background: {
      default: "hsl(0, 0%, 100%)"
    }
  }
});

const App = () => {
  const [mode, setMode] = useState("light");

  const selectedTheme = mode === "dark" ? darkTheme : lightTheme;

  return (
    <ThemeProvider theme={selectedTheme}>
      <CssBaseline />
      <Container maxWidth="lg">
        <h1>Hello</h1>
        <Switch onChange={() => setMode(mode === "light" ? "dark" : "light")} />
      </Container>
    </ThemeProvider>
  );
};

export default App;
3 Answers

According to the Material UI documentation, to switch between light and dark, they suggest useMemo to create a new theme on demand:

import { useState, useMemo } from "react";

function App() {
  const [mode, setMode] = useState("light");

  const theme = useMemo(
    () =>
      createTheme({
        palette: {
          type: mode,
          background: {
            dark: "hsl(230, 17%, 14%)",
            light: "hsl(0, 0%, 100%)"
          }
        }
      }),
    [mode]
  );

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Container maxWidth="lg">
        <h1>Hello</h1>
        <Switch onChange={() => setMode(mode === "light" ? "dark" : "light")} />
      </Container>
    </ThemeProvider>
  );
}

This works even when using StrictMode.

The reason it doesn't work with StrictMode when defined outside of the component is addressed in a Github issue, which states that this behaviour should be fixed in v5 (still in beta).

not sure why, but removing StrictMode in index.js fixed the problem

Related