【问题标题】:How to dynamically change palette type (dark/light) of theme using Switch and withStyles()如何使用 Switch 和 withStyles() 动态更改主题的调色板类型(暗/亮)
【发布时间】:2019-12-15 20:48:21
【问题描述】:

我正在尝试创建一个可以更改网站暗模式的开关。它在某种程度上适用于更改文本颜色。但是,即使使用 CssBaseline,背景和其他一切都保持不变

这里是重要的代码:

App.tsx


class App extends React.Component<Props, State> {
  curTheme: Theme;
  constructor(props: Props) {
    super(props);

    this.state = {
      theme: ThemeManagerInstance
    };

    this.curTheme = createMuiTheme(this.state.theme.getTheme);
  }


  render() {
    const classes = this.props.classes;
    this.curTheme = createMuiTheme(this.state.theme.getTheme);

    console.log("Dark status: " + (this.isDark()));

    return (
      <div className={classes.root}>
        <MuiThemeProvider theme={this.getTheme()}>
          <CssBaseline />
                 <FormControlLabel
                    control={
                      <Switch
                        checked={this.isDark()}
                        onChange={() => {
                          this.setState(state => {
                            this.state.theme.useDarkMode(
                              !this.isDark()
                            );
                            //   this.state.theme.getTheme().palette.type === // if (
                            //   "dark"
                            // ) {
                            //   this.state.theme.getTheme().palette.type =
                            //     "light";
                            // } else {
                            //   this.state.theme.getTheme().palette.type = "dark";
                            // }

                            console.log(this.getTheme().palette.type);

                            return state;
                          });
                        }}
                        color="primary"
                        value="dynamic-class-name"
                      />
                    }
                    label="Dark Mode"
                  />
          {/* code goes here */}
        </MuiThemeProvider>
      </div>
    );
  }



  getTheme() {
    return this.curTheme;
  }

  isDark() {
    return this.getTheme().palette.type === "dark"
  }
}

// export default App;

export default withStyles(
  styleJSON(createMuiTheme(ThemeManagerInstance.getTheme))
)(App);

主题.tsx

import blue from "@material-ui/core/colors/blue";
import createMuiTheme, {
  Theme,
  ThemeOptions
} from "@material-ui/core/styles/createMuiTheme";
import { PaletteOptions } from "@material-ui/core/styles/createPalette";
import { PaletteType } from "@material-ui/core";

const palette: PaletteOptions = {
  primary: {
    main: "#1976D2"
  },
  type: "light"
};

const defaultTheme = {
  palette: palette
};

export class ThemeManager {
  constructor(private theme: ThemeOptions) {
    this.useDarkMode(true);

    console.log(this.getTheme);
  }

  getThemePalette(): PaletteOptions | undefined {
    return this.theme.palette;
  }

  get getTheme() {
    return this.theme;
  }

  useDarkMode(dark: boolean) {
    const typeColor: PaletteType = dark ? "dark" : "light";

    const updatedTheme: ThemeOptions = {
      ...this.theme,
      palette: {
        ...this.theme.palette,
        type: typeColor
      }
    };

    this.theme = updatedTheme;
  }
}

const themeInstance = new ThemeManager(defaultTheme);

export default themeInstance;

index.js

ReactDOM.render(
    < App />,
    document.getElementById('root')
);

如果听起来我在要求 sponefeeding 代码,请原谅,但老实说,我很困惑,因为我不明白如何处理来自 withStyles() 的重新加载样式信息

【问题讨论】:

  • 我认为您的主要问题是状态管理。 useDarkMode 不调用 setState 所以它不会触发重新渲染。你有一个奇怪的实例变量组合(例如this.themethis.curTheme)和状态,这使得很难推断代码的正确性。我建议转换为函数组件(以便您不能使用实例变量)并为开关(深色与浅色)设置一个布尔状态变量,然后使用一个函数来创建基于该变量的主题布尔值。我认为最终结果会更容易理解和消除您的问题。
  • 是的,请原谅我的丑陋代码,我刚刚尝试了一段时间的新解决方案,但我通常会留下丑陋或不一致的代码。当我开始我的设置时,我会继续努力

标签: javascript reactjs typescript material-ui


【解决方案1】:

可以试试这个 https://github.com/bluelovers/ws-react/tree/master/packages/material-ui-theme-state

import { useTheme, createTheme } from 'material-ui-theme-state/esm/global';

创建主题

let bool = prefersLightMode();
let theme: ThemeOptions | Theme;
    let setTheme: IThemeExtra["setTheme"];

    ([theme, setTheme] = useState({
        palette: {
            type: bool ? 'light': 'dark',
        },
        //direction: 'rtl'
    }));
const muiTheme = createTheme(theme, {
        setTheme,
    }).theme;

    return (<MuiThemeProvider theme={muiTheme}>{props.children}</MuiThemeProvider>)

任何其他你想改变的主题

const { theme, setTheme } = useTheme();

setTheme(theme => {

                theme.palette.type = (theme.palette.type !== 'light') ? 'light' : 'dark';

            return theme;
        }, true)

现场演示 https://tpl-next-app.now.sh/

【讨论】:

  • 好吧,我认为我的主要问题是我的 App 组件在导出时被设置样式,即 ``` export default withStyles( styleJSON(createMuiTheme(ThemeManagerInstance.getTheme)) )(App); ```
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 1970-01-01
  • 2020-12-11
  • 2010-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多