简体   繁体   中英

Cannot use mui theme with emotion css prop

I am trying to implement a dark theme in the web app and moved my styling from just styles.css with overwriting using.important to emotion css prop.

Here is the code from App.tsx, where I create my theme and use ThemeProvider

const theme = createTheme({
  typography: {
    allVariants: {
      fontFamily: 'SFCompactDisplay',
    },
  },
  palette: {
    primary: {
      main: '#0052cc',
    },
  },
});

console.log(theme);

const App: React.FC = () => (
  <ThemeProvider theme={theme}>
    <Switch>
      <Route path="/login" component={Login} exact />
      <ProtectedRoute path="/" component={Dashboard} exact />
      {/* <Route path="/register" component={Register} /> */}
      <Redirect to="/" />
    </Switch>
    <Toaster
      position="top-right"
      toastOptions={{
        style: {
          fontWeight: 400,
        },
      }}
    />
  </ThemeProvider>
);

Also, here is the code from css.ts, which I then use in one of the components

export const splitContainer = (theme) => {
  console.log(theme);
};

export const content: CSSWithTheme = (theme) => ({
  maxWidth: '800px',
  width: '100%',
  [theme.breakpoints.down('md')]: {
    padding: '0 24px',
    maxWidth: '100%',
  },
});

I get an error stating that any property of theme is undefined. I consoled logged both themes, the first one, in App looks as normal MUI theme with breakpoints, pallete properties, but the one in css.ts looks like this:

在此处输入图像描述

I use the splitContainer in Dashboard component

  return (
    <Box css={css.splitContainer}>
      <SideBar tab={tab} setTab={setTab} />
      <Box className="container-main-overview">
        {tab === 1 && <MachineList />}
        {tab === 4 && <AddInstance />}
        {tab === 5 && <Support />}
      </Box>
    </Box>
  );

The styles work, however when I try to use the theme, I get undefined error

As per @Ryan Cogswell mentioned, you need to declare the Emotion theme provider as well. Since Emotion's theme is an empty object, you can pass the MUI theme as is. If you use typescript, you will need to extend emotion's theme interface. If you need to handle dark mode, you can have your own theme provider (based on React's context API) to switch the light and dark themes and to combine the above mentioned two, MUI and emotion providers.

Here is a small example for the context provider (without the context definition)

const ThemeProvider: FC<ThemeProviderProps> = ({ children }) => {
  const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
  const defaultTheme = useMemo<ThemeContextProps['themeMode']>(
    () => (prefersDarkMode ? 'dark' : 'light'),
    [prefersDarkMode],
  );

  const [themeMode, setThemeMode] =
    useState<ThemeContextProps['themeMode']>(defaultTheme);

  const toggleTheme = useCallback(() => {
    setThemeMode((prevValue) => 
      (prevValue === 'light' ? 'dark' : 'light'));
  }, []);

  const providerProps = useMemo(
    () => ({
      themeMode,
      theme: themeMode === 'light' ? lightTheme : darkTheme,
      toggleTheme,
    }),
    [themeMode, toggleTheme],
  );

  return (
    <ThemeContext.Provider value={providerProps}>
      <MuiThemeProvider theme={providerProps.theme}>
        <EmotionThemeProvider theme={providerProps.theme}>
          {children}
        </EmotionThemeProvider>
      </MuiThemeProvider>
    </ThemeContext.Provider>
  );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM