如何在样式化组件中访问 Material-ui 的主题
Posted
技术标签:
【中文标题】如何在样式化组件中访问 Material-ui 的主题【英文标题】:How do I access Material-ui's theme in Styled Component 【发布时间】:2019-11-28 05:21:53 【问题描述】:我将 CRA 与 Material-ui 和 Styled Components 类型的样式一起使用。 在构建我的 CSS 时,我想访问 Material-ui 的默认主题。
package.json 的一部分:
"dependencies":
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1",
"@material-ui/core": "^4.2.1",
"@material-ui/icons": "^4.2.1",
"@material-ui/styles": "^4.2.1",
"styled-components": "^4.3.2"
当我尝试下面的theme
时,props
上存在但它是一个空对象。
StyledApp.js:
import styled from "styled-components";
import Button from "@material-ui/core/Button";
export const StyledButtonUsingTheme = styled(Button)`
//Below will give "Cannot read property 'error' of undefined"
background-color: $props => props.theme.palette.error.light;
`;
App.js:
import React from "react";
import "./App.css";
import StylesProvider, ThemeProvider from "@material-ui/styles";
import createMuiTheme from "@material-ui/core/styles";
import StyledButtonUsingTheme from "./StyledApp";
function App()
const defaultTheme = createMuiTheme();
window.console.log("Default theme passing to ThemeProvider", defaultTheme);
return (
<StylesProvider injectFirst>
<ThemeProvider theme=defaultTheme>
<div className="App">
<StyledButtonUsingTheme variant="outlined">
Styled Button Using Theme
</StyledButtonUsingTheme>
</div>
</ThemeProvider>
</StylesProvider>
);
export default App;
App.js
中的 console.log 显示了整个主题对象,这就是我传递给 ThemesProvider 的内容。有趣的是props.theme
在那里!但遗憾的是没有价值。
【问题讨论】:
我有一个解决方法:在 StyledApp.js 中使用: background-color: $props => createMuiTheme().palette.error.light; ...但是每次我想使用主题时调用 createMuiTheme() 感觉就像是一种黑客攻击 但是您不能以任何方式将theme
传递给StyledButtonUsingTheme
。我不明白这是怎么回事
我希望将主题添加到 styled
。 import styled from '@material-ui/styles';
codesandbox.io/s/pedantic-kapitsa-l3bn3 从material-ui.com/guides/interoperability/#themeprovider 复制并粘贴示例。
【参考方案1】:
您可以使用 withTheme :
App.js
import React from "react"
import ThemeProvider, createMuiTheme from "@material-ui/core/styles"
import StyledButton from "./StyledButton"
const App = () =>
const theme = createMuiTheme();
return (
<ThemeProvider theme=theme>
<StyledButton />
</ThemeProvider>
)
export default App
StyledButton.js
import styled, withTheme from "@material-ui/core/styles"
import Button from "@material-ui/core/Button"
export const StyledButton= styled(withTheme(Button))(props => (
background: props.theme.palette.background.paper,
))
【讨论】:
【参考方案2】:正如 Horyd 在评论中所说,使用 Styled-Components
中的 ThemeProvider
将使您能够访问样式化组件中的主题属性。
但是 Material-UI 不再将该主题应用到它自己的组件中。
我发现的解决方法既丑陋又简单:同时使用 Themeproviders。因此 Material-UI 将主题应用于其组件,您可以在样式化的组件中访问主题。
import ThemeProvider from "styled-components";
import MuiThemeProvider,StylesProvider from "@material-ui/core/styles";
ReactDOM.render(
//Make sure the Material stylesheet is placed above your own
//styles so you can overwrite them
<StylesProvider injectFirst>
//Use the theme in the ThemeProvider for Material-UI so
//styles are applied to the Material-UI components
<MuiThemeProvider theme=theme>
//Use also the ThemeProvider for Styled-Components so
//you can access the theme in your own css
<ThemeProvider theme=theme>
//Include your app and you have acces to everything
<App />
</ThemeProvider>
</MuiThemeProvider>
</StylesProvider>,
document.getElementById("app"));
【讨论】:
对于 MUI v5,使用ThemeProvider
代替 MuiThemeProvider
和 StyledEngineProvider
代替 StylesProvider
【参考方案3】:
withTheme 使用的答案几乎是完整的。最后一部分对我不起作用,所以我改为:
import styled from 'styled-components'
import withTheme from "@material-ui/core/styles"
const StyledButton = withTheme(styled('h1')`
background-color: $props => props.theme.palette.error.light;
`
)
【讨论】:
【参考方案4】:问题解决了!
解决方案是使用:
import ThemeProvider from "styled-components";
在 App.js 中,然后 theme
包含 props
对象上的所有值。
我在 App.js 中使用了来自“@material-ui/styles”的 ThemeProvider
import StylesProvider, ThemeProvider from "@material-ui/styles";
这与 StyledApp.js 中的 `import styled from "styled-components" 效果不佳
工作的两个文件:
App.js
import React from "react";
import "./App.css";
import StylesProvider from "@material-ui/styles";
import ThemeProvider from "styled-components";
import createMuiTheme from "@material-ui/core/styles";
import StyledButtonUsingTheme from "./StyledApp";
function App()
const defaultTheme = createMuiTheme();
window.console.log("Default theme passing to ThemeProvider", defaultTheme);
return (
<StylesProvider injectFirst>
<ThemeProvider theme=defaultTheme>
<div className="App">
<StyledButtonUsingTheme variant="outlined">
Styled Button Using Theme
</StyledButtonUsingTheme>
</div>
</ThemeProvider>
</StylesProvider>
);
export default App;
StyledApp.js
import styled from "styled-components";
import Button from "@material-ui/core/Button";
export const StyledButtonUsingTheme = styled(Button)`
//Below will work now!
background-color: $props => props.theme.palette.error.light;
`;
【讨论】:
我不确定这是否真的解决了同时为使用styled
构造的样式化组件提供主题以及自动将主题应用于<Button color="primary">Click me</Button>
等material-ui 组件的问题。使用您的解决方案,第二个示例不符合主题【参考方案5】:
如果您想同时使用 ThemeProviders,首先来自 styled-components,其次来自 material-ui,您可以为其中一个使用 alias:
import ThemeProvider as StyledThemeProvider from 'styled-components';
import ThemeProvider from '@material-ui/core/styles';
function App()
return (
<Router>
<ThemeProvider theme=theme>
<StyledThemeProvider theme=theme>
<Wrapper>
<TheHeader />
<TheContent />
<TheFooter />
</Wrapper>
</StyledThemeProvider>
</ThemeProvider>
</Router >
);
export default App;
【讨论】:
【参考方案6】:在我的例子中,我发现theme
对象是自动与styled
component一起传入的,可以通过如下参数访问:
import React from 'react';
import styled from '@material-ui/core';
const StyledButton = styled('button')(( theme ) => (
color: theme.palette.text.secondary,
));
我在 MUI v4.11.0 中有这个工作。
【讨论】:
谢谢!这节省了我的精力,因为我有大量样式化的组件并且不想到处实现withTheme
【参考方案7】:
在您的样式组件中,您可以使用钩子 useTheme 示例:
import useTheme from "@material-ui/core"
import styled from "@material-ui/styles"
const theme = useTheme
const StyledListbox = styled("ul")(
backgroundColor: theme.palette.primary.main,
)
【讨论】:
以上是关于如何在样式化组件中访问 Material-ui 的主题的主要内容,如果未能解决你的问题,请参考以下文章
使用 React.js 和 Material-UI 简化样式化的组件媒体查询
样式化 Material-UI Drawer 组件与 Styled Components