在非材质ui组件中的黑暗和明亮主题之间切换

时间:2020-07-19 06:13:01

标签: reactjs material-ui

我正在尝试在我的应用程序中引入主题切换器。我有很多非材料用户界面元素,我需要主题来反映它们的变化。

下面的代码显示我有一个称为darkState的状态,该状态设置为true。我的应用程序中的主要ui组件反映了这些更改,但是例如下面的div并未获得深色主题的深色。我在这里做错什么了?

import React, { useState } from "react";
import Header from "./components/Header.js";
import TopBar from "./components/TopBar.js";
import Sequence from "./components/Sequence.js";
import SecondaryWindow from "./components/SecondaryWindow.js";

import { MuiThemeProvider, createMuiTheme, makeStyles } from "@material-ui/core/styles";

import "./App.css";
import { MainContextProvider } from "./contexts/mainContext.js";

function App() {
    const [darkState, setDarkState] = useState(true);
    const palletType = darkState ? "dark" : "light";
    const theme = createMuiTheme({
        palette: {
            secondary: {
                main: "#0069ff",
            },
            type: palletType,
        },
    });
    const useStyles = makeStyles((theme) => ({
        root: {
            paddingLeft: 80,
            height: "100%",
            backgroundColor: theme.palette.background.default,
        },
    }));
    const classes = useStyles();
    return (
        <MuiThemeProvider theme={theme}>
            <MainContextProvider>
                <div className={classes.root}>
                    <Header />
                    <TopBar />
                    <Sequence />
                    <SecondaryWindow />
                </div>
            </MainContextProvider>
        </MuiThemeProvider>
    );
}

export default App;

4 个答案:

答案 0 :(得分:1)

这是因为仅更改@material组件而不更改CSS,要更改CSS主题,您需要为Dark Theme的CSS变量。

:root上声明所有浅色主题颜色,在div.darkmode上声明所有暗色模式:

:root {
  --color-bg: #fff;
  --color-text: #000;
}

.div.darkmode {
  --color-bg: #363636;
  --color-text: #d1d1d1;
}

/** Usage */
.div {
   color: var(--color-text);
   background: var(--color-bg)
}

并在黑暗主题为真时在div上创建条件,就像您在上面编写的那样,将添加一个新的类名darkmode进行潜水

<div className={`${classes.root} ${darkState && `darkmode`}`}>
    <Header />
    <TopBar />
    <Sequence />
    <SecondaryWindow />
</div>

我创建了an example for you here。 让我们知道是否有任何问题!


解决方法2

如果您没有按CSS文件进行任何客户样式设置,则可以使用

import React from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';

export default function MyApp() {
  return (
    <MuiThemeProvider theme={theme}>
      <CssBaseline />
      {/* The rest of your application */}
    </MuiThemeProvider>
  );
}

答案 1 :(得分:1)

现在我知道了答案,在我的示例中,类root无法从theme提供的自定义创建的MuiThemeProvider中受益。而是使用Mui随附的原始theme。为了解决这个问题,我将div分成了一个组件。这样,theme可以访问div上下文(来自MuiThemeProvider的自定义主题)。这样,当我切换DarkState时,颜色会基于自定义主题调色板在Mui组件和HTML元素上更新。

import React, { useContext, useState } from "react";
import Header from "./components/Header.js";
import TopBar from "./components/TopBar.js";
import Sequence from "./components/Sequence.js";
import SecondaryWindow from "./components/SecondaryWindow.js";

import { MuiThemeProvider, createMuiTheme, makeStyles } from "@material-ui/core/styles";

import "./App.css";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { MainContextProvider } from "./contexts/mainContext.js";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";

function AppContent() {
    const useStyles = makeStyles((theme) => ({
        root: {
            paddingLeft: 80,
            height: "100%",
            backgroundColor: theme.palette.background.default,
        },
    }));
    const classes = useStyles();
    return (
        <div className={classes.root}>
            <Header />
            <TopBar />
            <Sequence />
            <SecondaryWindow />
        </div>
    );
}
function App() {
    const [darkState, setDarkState] = useState(true);
    const palletType = darkState ? "dark" : "light";
    const theme = createMuiTheme({
        palette: {
            secondary: {
                main: "#0069ff",
            },
            type: palletType,
        },
    });
    return (
        <MuiThemeProvider theme={theme}>
            <MainContextProvider>
                <AppContent />
            </MainContextProvider>
        </MuiThemeProvider>
    );
}

export default App;

答案 2 :(得分:0)

我将主题的两个变体都声明为安装或渲染之上的常量。这样,您每次交换主题时就不会真正创建新主题。我会有一个状态,保持对MUI-Theme常量的引用。

答案 3 :(得分:0)

您可以操纵data-theme属性来切换暗/亮主题。在 StackBlitz 上尝试。

设置主题

使用data-theme属性设置所选主题。

/* default theme (light) */
:root {
  --primary-color: #302ae6;
  --secondary-color: #536390;
  --font-color: #424242;
  --bg-color: #fff;
}

/* dark theme */
[data-theme='dark'] {
  --primary-color: #9a97f3;
  --secondary-color: #818cab;
  --font-color: #e1e1ff;
  --bg-color: #161625;
}

React Hooks中的切换主题

// App.js

const [theme, setTheme] = useState({
  light: true,
});

const handleChangeTheme = (event) => {
  setTheme({ ...theme, [event.target.name]: event.target.checked });
};

相应地设置我们的data-theme属性

const currentTheme = theme.light === true ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', currentTheme);