Material UI: Dark theme not being applied

Viewed 1833

I'm using the Context API to store the theme value. The theme itself is created with <createMuiTheme> and passed down from <Layout> to children via <MuiThemeProvider> and <CssBaseline>. I can see the state change via React DevTools but the theme itself is not being applied - and I'm at loss as to why...

Here is codesandbox with a full example - warning: contains Samuel L. Ipsum. What follows is an abridged version.

Default and dark theme definitions:

// theme/dark.js
import { createMuiTheme } from "@material-ui/core/styles";

const theme = createMuiTheme({
  typography: {
    useNextVariants: true
  },
  palette: {
    type: "dark"
  }
});

export default theme;

// theme/default.js
import { createMuiTheme } from "@material-ui/core/styles";

const theme = createMuiTheme({
  typography: {
    useNextVariants: true
  },
  palette: {
    type: "light"
  }
});

export default theme;

Context:

// context/settings/SettingsContext.js
import React from "react";

export default React.createContext({
  darkMode: false
});

// context/settings/SettingsProvider.js
import React, { useState } from "react";
import SettingsContext from "./SettingsContext";

const storage = {
  getItem(key) {
    if (localStorage) {
      return localStorage.getItem(key);
    }
  },
  setItem(key, value) {
    if (localStorage) {
      return localStorage.setItem(key, value);
    }
  }
};

const SettingsProvider = props => {
  const [darkMode, setDarkMode] = useState(
    storage.getItem("darkMode") === "true"
  );
  const onSetDarkMode = darkMode => {
    setDarkMode(darkMode);
    storage.setItem("darkMode", darkMode);
  };
  return (
    <SettingsContext.Provider
      value={{
        darkMode,
        onSetDarkMode
      }}
    >
      {props.children}
    </SettingsContext.Provider>
  );
};

export default SettingsProvider;

index.js:

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./containers/app";
import SettingsProvider from "./context/settings/SettingsProvider";

ReactDOM.render(
  <BrowserRouter>
    <SettingsProvider>
      <App />
    </SettingsProvider>
  </BrowserRouter>,
  document.getElementById("root")

app/index.js:

import React, { useState } from "react";
import { Switch, Route } from "react-router-dom";
import { default as home } from "../home/routes";
import Layout from "../layout";

const App = () => {
  const [anchorEl, setAnchorEl] = useState(null);
  return (
    <div>
      <Layout anchorEl={anchorEl} setAnchorEl={setAnchorEl}>
        <Switch>
          {home.map((route, index) => (
            <Route
              key={index}
              path={route.path}
              exact={route.exact}
              render={route.render}
            />
          ))}
        </Switch>
      </Layout>
    </div>
  );
};

export default App;

And layout/index.js:

import React, { useContext } from "react";
import { MuiThemeProvider } from "@material-ui/core/styles";
import { makeStyles } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import defaultTheme from "../../themes/default";
import darkTheme from "../../themes/default";
import SettingsContext from "../../context/settings/SettingsContext";
import Header from "../../components/header/index";

const useStyles = makeStyles(theme => ({
  toolbarMargin: {
    ...theme.mixins.toolbar
  }
}));

const Layout = props => {
  const classes = useStyles();
  const context = useContext(SettingsContext);
  const theme = context.darkMode ? darkTheme : defaultTheme;
  const { children, anchorEl, setAnchorEl } = props;

  return (
    <MuiThemeProvider theme={theme}>
      <CssBaseline />
      <Header anchorEl={anchorEl} setAnchorEl={setAnchorEl} />
      <main>
        <div className={classes.toolbarMargin} />
        {children}
      </main>
    </MuiThemeProvider>
  );
};

export default Layout;

What did I miss?

1 Answers

You're importing the same theme twice. I'd suggest using named exports instead of defaults, it helps a lot with auto importing, as well as spotting mistakes like this.

// layout/index.js

import defaultTheme from "../../themes/default";
import darkTheme from "../../themes/default"; // should be "../../theme/dark"
Related