如何在 Styled Component 中访问 Material-ui 的主题
How do I access Material-ui's theme in Styled Component
我将 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
在那里!但遗憾的是没有价值观。
问题已解决!
解决方案是使用:
import { ThemeProvider } from "styled-components";
在 App.js 然后 theme
和 props
对象上的所有值都在那里。
我在 App.js 中使用了来自“@material-ui/styles”的 ThemeProvider
import { StylesProvider, ThemeProvider } from "@material-ui/styles";
这与在 StyledApp.js
中从 "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;
样式化App.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};
`;
正如 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"));
你可以使用 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,
}))
使用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};
`
)
如果你想使用两个 ThemeProvider,第一个来自 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;
在您的样式组件中,您可以使用挂钩 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,
})
在我的例子中,我发现 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 中使用此功能。
对于 MUI v5:
index.tsx
import { ThemeProvider, createTheme } from "@mui/material/styles";
import { StyledEngineProvider} from "@mui/material";
import { ThemeProvider as ScThemeProvider } from "styled-components";
import App from "components/App/App";
const theme = createTheme();
ReactDOM.render(
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<ScThemeProvider theme={theme}>
<App />
</ScThemeProvider>
</ThemeProvider>
</StyledEngineProvider>,
document.getElementById("root")
);
我在 MUI v5 中是这样做的
import { styled as muiStyled } from '@mui/material';
const NavLinkStyle = muiStyled('div')(({ theme }) => ({
padding: '0 10px',
height: '100%',
fontWeight: 'bold',
'&:hover': {
color: theme.palette.primary.main,
cursor: 'pointer',
borderRadius: '15px'
}
}));
我将 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
在那里!但遗憾的是没有价值观。
问题已解决!
解决方案是使用:
import { ThemeProvider } from "styled-components";
在 App.js 然后 theme
和 props
对象上的所有值都在那里。
我在 App.js 中使用了来自“@material-ui/styles”的 ThemeProvider
import { StylesProvider, ThemeProvider } from "@material-ui/styles";
这与在 StyledApp.js
工作的两个文件:
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;
样式化App.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};
`;
正如 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"));
你可以使用 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,
}))
使用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};
`
)
如果你想使用两个 ThemeProvider,第一个来自 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;
在您的样式组件中,您可以使用挂钩 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,
})
在我的例子中,我发现 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 中使用此功能。
对于 MUI v5:
index.tsx
import { ThemeProvider, createTheme } from "@mui/material/styles";
import { StyledEngineProvider} from "@mui/material";
import { ThemeProvider as ScThemeProvider } from "styled-components";
import App from "components/App/App";
const theme = createTheme();
ReactDOM.render(
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<ScThemeProvider theme={theme}>
<App />
</ScThemeProvider>
</ThemeProvider>
</StyledEngineProvider>,
document.getElementById("root")
);
我在 MUI v5 中是这样做的
import { styled as muiStyled } from '@mui/material';
const NavLinkStyle = muiStyled('div')(({ theme }) => ({
padding: '0 10px',
height: '100%',
fontWeight: 'bold',
'&:hover': {
color: theme.palette.primary.main,
cursor: 'pointer',
borderRadius: '15px'
}
}));