How do I access Material-ui's theme in Styled Component

吃可爱长大的小学妹 提交于 2020-07-20 07:07:04

问题


I'm using CRA with Material-ui and Styled Components type of styling. When building my CSS I want to access Material-ui's default theme.

part of 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"
  }

When I try the below theme exists on props but is an empty object.

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;

The console.log in App.js shows the whole theme object, and that's what I pass to ThemesProvider. Interestingly props.theme is there! but sadly with no values.


回答1:


As Horyd in the comment says, using the ThemeProvider from Styled-Components will give you access to the theme properties inside your styled component. But Material-UI doesn't apply that theme anymore to its own components.

The workaround I found is as ugly as it is simple: Use both Themeproviders. So Material-UI applies the theme to its components and you can access the theme in your styled components.

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"));



回答2:


You could use 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,
}))



回答3:


Problem Solved!

The solution is to use: import { ThemeProvider } from "styled-components"; in App.js then the theme is there with all the values on the props object.

I used ThemeProvider from "@material-ui/styles" in App.js import { StylesProvider, ThemeProvider } from "@material-ui/styles"; That doesn't play well with `import styled from "styled-components" in StyledApp.js

The working two files:

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};
`;



回答4:


The answer which used withTheme is almost complete. The last part didn't work for me, so I changed to:

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};
  `
)


来源:https://stackoverflow.com/questions/57108648/how-do-i-access-material-uis-theme-in-styled-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!