Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Material UI Theme Change

can you please help me to change the React Material UI theme Dynamically .

https://i.sstatic.net/cdbgS.jpg https://i.sstatic.net/qRxPm.jpg

I have tried by changing the theme Properties on button click . The theme properties are getting changed as seen in the console . But the change is not reflecting on the theme .

Sandbox Code : https://codesandbox.io/s/30qwyk92kq

const themeChange = () => {
  alert(theme);
  theme.palette.type = "light";
  console.log(theme);
};
ReactDOM.render(
  <MuiThemeProvider theme={theme}>
    <React.Fragment>
      <CssBaseline />
      <App changeTheme={themeChange} />
    </React.Fragment>
  </MuiThemeProvider>,
  document.getElementById("app")
);

When I click the button the theme has to change to Dark color

like image 619
Murali V Avatar asked Sep 05 '26 08:09

Murali V


1 Answers

I am using styledComponents, typescript and material-ui.

First I defined my themes:

// This is my dark theme: dark.ts
// I defined a light.ts too
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';

export const darkTheme = createMuiTheme({
  palette: {
    type: 'dark',   // Name of the theme
    primary: {
      main: '#152B38',
    },
    secondary: {
      main: '#65C5C7',
    },
    contrastThreshold: 3,
    tonalOffset: 0.2,
  },
});

I defiend a themeProvider function and in this function I wrapped the material-ui's ThemeProvider in a React context to be able to change the theme easily:

import React, { useState } from 'react';
import {ThemeProvider} from "@material-ui/core/styles/";
import { lightTheme } from "./light";
import { darkTheme } from "./dark";

const getThemeByName = (theme: string) => {
  return themeMap[theme];
}

const themeMap: { [key: string]: any } = {
  lightTheme,
  darkTheme
};

export const ThemeContext = React.createContext(getThemeByName('darkTheme'));

const ThemeProvider1: React.FC = (props) => {
  // State to hold the selected theme name
  const [themeName, _setThemeName] = useState('darkTheme');

  // Retrieve the theme object by theme name
  const theme = getThemeByName(themeName);

  return (
        <ThemeContext.Provider value={_setThemeName}>
            <ThemeProvider theme={theme}>{props.children}</ThemeProvider>
        </ThemeContext.Provider>
    );
}
export default ThemeProvider1;

Now I can use it in my components like this:

import React from 'react';
import styled from 'styled-components';
import useTheme from "@material-ui/core/styles/useTheme";

const MyCardHeader = styled.div`
                        width: 100%;
                        height: 40px;
                        background-color: ${props => props.theme.bgColor}; 
                        color: ${props => props.theme.txtColor}; 
                        display: flex;
                        align-items:center;
                        justify-content: center;
                    `;

export default function CardHeader(props: { title: React.ReactNode; }) {
    const theme = {
        bgColor: useTheme().palette.primary.main, 
        txtColor: useTheme().palette.primary.contrastText
    };

    return (
        <MyCardHeader theme={theme}>
            {props.title}
        </MyCardHeader>
    );
}

For Changing between themes:

import React, {useContext} from 'react';
import { ThemeContext} from './themes/themeProvider';


export default function Header() {
    // Get the setter function from context
    const setThemeName = useContext(ThemeContext);
    
    return (
        <header>
            <button onClick={() => setThemeName('lightTheme')}>
                light
            </button>
            <button onClick={() => setThemeName('darkTheme')}>
                dark
            </button>
        </header>
    );
}
like image 137
Ashkan Avatar answered Sep 08 '26 05:09

Ashkan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!