React Material UI主题更改

时间:2019-04-25 10:03:53

标签: reactjs material-ui

能帮我动态更改React Material UI主题吗?

https://imgur.com/S8zsRPQ https://imgur.com/Ul8J40N

我尝试通过更改按钮单击上的主题属性来进行尝试。如在控制台中所示,主题属性正在更改。但是这种变化并没有反映出主题。

沙盒代码: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")
);

当我单击按钮时,主题必须更改为深色

2 个答案:

答案 0 :(得分:2)

我正在使用styledComponentstypescriptmaterial-ui

首先,我定义了主题:

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

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

我无视一个themeProvider函数,在这个函数中,我将Material-ui的ThemeProvider包装在React上下文中,以便能够轻松更改主题:

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;

现在我可以在我的组件中使用它了,

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>
    );
}

在主题之间切换:

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>
    );
}

答案 1 :(得分:0)

在您的代码中,主题类型已更改。但是Page不会重新呈现新主题。

我已经更改了index.js和App.js中的代码,如下所示。 试试这种方法。可以。

index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <App/>,
  document.getElementById("app")
);

App.js

import React from "react";
import CssBaseline from "@material-ui/core/CssBaseline";
import Typography from "@material-ui/core/Typography";
import { Button } from "@material-ui/core";
import { MuiThemeProvider, createMuiTheme } from "@material-ui/core/styles";
import blueGrey from "@material-ui/core/colors/blueGrey";
import lightGreen from "@material-ui/core/colors/lightGreen";

class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      themeType : 'dark',
    }
  }

  changeTheme(){
    if (this.state.themeType == 'dark'){
      this.setState({themeType:'light'});
    } else {
      this.setState({themeType:'dark'});
    }
  }
  render() {
    let theme = createMuiTheme({
      palette: {
        primary: {
          light: lightGreen[300],
          main: lightGreen[500],
          dark: lightGreen[700]
        },
        secondary: {
          light: blueGrey[300],
          main: blueGrey[500],
          dark: blueGrey[700]
        },
        type: this.state.themeType
      }
    });
    return (
      <MuiThemeProvider theme={theme}>
        <CssBaseline />
        <Typography>Hi there!</Typography>
        <Button
          variant="contained"
          color="secondary"
          onClick={()=>{this.changeTheme()}}
        >
          Change
        </Button>
      </MuiThemeProvider>
    );
  }
}
export default App;