reactjs - 从嵌套组件更改 MUI 主题
问题描述
我有以下组件结构:
App -> ThemeProvider -> MenuBar -> ThemeControls -> Switch and Autocomplete
我想使用开关更改为暗模式并使用自动完成更改原色。为此,我添加了以下自定义挂钩。
import {createMuiTheme} from "@material-ui/core";
import {useState} from "react";
/**
* Hook to change the theme
*
* @returns {Theme, () => setDarkMode}
*/
const useThemeBuilder = () => {
const [myTheme, setMyTheme] = useState({})
console.log('myTheme:', myTheme);
let theme = createMuiTheme(myTheme);
console.log('theme:' , theme);
return [theme, setMyTheme]
}
export default useThemeBuilder;
该钩子需要一个主题对象来覆盖默认对象createMuiTheme
。主题对象和改变钩子状态的回调被暴露了!
这是该对象的外观示例:
{
"palette": {
"type": "light",
"primary": {
"50": "#ffebee",
"100": "#ffcdd2",
"200": "#ef9a9a",
"300": "#e57373",
"400": "#ef5350",
"500": "#f44336",
"600": "#e53935",
"700": "#d32f2f",
"800": "#c62828",
"900": "#b71c1c",
"A100": "#ff8a80",
"A200": "#ff5252",
"A400": "#ff1744",
"A700": "#d50000"
}
}
}
我现在的问题是App.js
不会重新渲染并且思想不会注入新主题。
这是我的app.js
import './App.css';
import React from 'react';
import {BrowserRouter as Router, Route, Switch,} from "react-router-dom";
import {MyComponent} from "./components/MyComponent";
import {ThemeProvider, useTheme} from "@material-ui/core/styles";
import {MenuBar} from "./components/MenuBar";
import {MyButtons} from "./components/MyButtons";
import {Home} from "./components/Home";
import {MyForms} from "./components/MyForms";
import {MyHookedForm} from "./components/MyHookedForm";
import {MyCarousel} from "./components/MyCarousel";
import useThemeBuilder from "./components/theme/theme";
import {CssBaseline} from "@material-ui/core";
function App() {
const [theme] = useThemeBuilder();
console.log('theme from App:', theme)
return (
<Router>
<ThemeProvider theme={theme}>
<CssBaseline/>
<MenuBar/>
<Switch>
<Route path="/colors">
<MyComponent/>
</Route>
<Route path="/buttons">
<MyButtons/>
</Route>
<Route path="/forms">
<MyForms/>
</Route>
<Route path="/hook-forms">
<MyHookedForm/>
</Route>
<Route path="/carousel">
<MyCarousel/>
</Route>
<Route path="/">
<Home/>
</Route>
</Switch>
</ThemeProvider>
</Router>
);
}
export default App;
解决方案
你需要的是一个上下文。由于您使用的是 useState ,因此每个使用钩子的组件都有自己的主题和 setMyTheme 变量。您应该创建一个导出 setMyTheme 函数的上下文提供程序。
你可以做这样的事情
import './App.css';
import React from 'react';
import {BrowserRouter as Router, Route, Switch,} from "react-router-dom";
import {MyComponent} from "./components/MyComponent";
import {ThemeProvider, useTheme} from "@material-ui/core/styles";
import {MenuBar} from "./components/MenuBar";
import {MyButtons} from "./components/MyButtons";
import {Home} from "./components/Home";
import {MyForms} from "./components/MyForms";
import {MyHookedForm} from "./components/MyHookedForm";
import {MyCarousel} from "./components/MyCarousel";
import useThemeBuilder from "./components/theme/theme";
import {CssBaseline} from "@material-ui/core";
const ThemeContext = React.createContext({theme:{}});
export const useMyTheme = ()=>React.useContext(ThemeContext);
function App() {
const [theme,setMyTheme] = useState({});
console.log('theme from App:', theme)
return (
<ThemeContext.Provider value={{theme,setMyTheme}}>
<Router>
<ThemeProvider theme={theme}>
<CssBaseline/>
<MenuBar/>
<Switch>
<Route path="/colors">
<MyComponent/>
</Route>
<Route path="/buttons">
<MyButtons/>
</Route>
<Route path="/forms">
<MyForms/>
</Route>
<Route path="/hook-forms">
<MyHookedForm/>
</Route>
<Route path="/carousel">
<MyCarousel/>
</Route>
<Route path="/">
<Home/>
</Route>
</Switch>
</ThemeProvider>
</Router>
<ThemeContext.Provider>
);
}
export default App;
在你想要使用它的组件中你可以做
const {theme,setMyTheme} = useMyTheme();
推荐阅读
- python - 使用 django-hosts 时使用的正确命名空间是什么
- asp.net - 在刷新之前已经设置了标头,并且仍然收到“发送 HTTP 标头后服务器无法设置内容类型”
- list - 如何生成特定大小的整数分区
- javascript - 使用 Javascript 更改引导主题
- python - 如何在浏览器中手动解决 reCaptcha
- java - Spring REST API 架构
- heroku - 对爱好和专业的 Heroku 定价感到困惑(标准 1x)
- javascript - 有没有办法避免在我的代码中使用 forceupdate ?
- ruby-on-rails - 猴子如何修补动作文本的表单助手以排除活动存储依赖关系?
- react-native - React Native onPress 事件返回未定义