Search code examples
reactjsmaterial-uicustom-theme

Is there a way to update Material UI theme palette primary and secondary color at runtime?


There is a set of default theme palette colors in our application, however for white labelling purpose I get theme primary and secondary color from API. Is there any way I can update those colors at runtime after receiving the values from API?

I am wrapping the MUI themeProvider at App level

import { ThemeProvider, StylesProvider } from '@material-ui/styles';
 import { createMuiTheme } from '@material-ui/core';
 
 
 const App = () => {
const customTheme = createMuiTheme({
  palette: {
   primary: {
      main: "#fff0c9", 
   },
   secondary: {
      main: '#FF8200',
   }
});
 
return(
    <ThemeProvider theme={customTheme}> 
      <div> Component </div>
   </ThemeProvider>)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

After loading the component, an API call receive the updated primary and secondary colors for each clients. Is there any way to update it at runtime?


Solution

  • You can store the desired colors in state and update that state with new colors. Then, you use that state in createMuiTheme() to set the primary and secondary colors. You may also want to use React.memo().

    Here's an example for setting random colors:

    const { useMemo, useState } = React;
    const {
      AppBar,
      Button,
      createMuiTheme,
      CssBaseline,
      ThemeProvider,
      Toolbar
     } = MaterialUI;
     
    const randomColor = () =>
      `#${Math.floor(Math.random() * 16777215).toString(16)}`;
    
    const App = () => {
      const [primary, setPrimary] = useState(randomColor);
    
      const theme = useMemo(
        () =>
          createMuiTheme({
            palette: {
              primary: { main: primary }
            }
          }),
        [primary]
      );
    
      const setRandomPrimary = () => setPrimary(randomColor);
    
      return (
        <ThemeProvider theme={theme}>
          <CssBaseline />
          <AppBar color="primary">
            <Toolbar />
          </AppBar>
          <Toolbar />
          <Button onClick={setRandomPrimary}>Change Color</Button>
        </ThemeProvider>
      );
    }
    
    ReactDOM.render(<App />, document.body);
    <script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.production.min.js"></script>

    This was based on this documentation.

    The random color function came from CSS-Tricks.