Material-UI ThemeProvider overwrites styles globally instead of only for wrapped components

1.5k views Asked by At

I have a React Component with multiple Material-UI Selects. Now I wanted to overwrite some styles of one of them so I created a theme and now want to apply it wit the ThemeProvider. My problem is that the ThemeProvider overwrites the styles of every Select and not only of the one it is wrapped around.

When googling I found a lot of questions how to make ThemeProvider apply its overwrites globally but that is the opposite of what I am trying to do. I want the ThemeProvider to apply its overwrites only to the Components, that it wraps around. Is there a better alternative to using ThemeProvider in my usecase? If yes, it has to work with class based Components (because I am using one here)

Codesandbox that shows my problem: https://codesandbox.io/s/twilight-sun-vyl9i

I am fairly new to Material-UI, so forgive me if I do something fundamentally wrong.

2

There are 2 answers

1
Daniel On BEST ANSWER

OK, I found the solution myself. According to this issue on the material-ui github , there is a v4 bug that multiple ThemeProviders must have a parent ThemeProvider element. According to them it will be fixed in the upcoming v5.

So what I did, I just wrapped a <ThemeProvider> around my <div className="App"> without giving it a theme prop.

0
user7247147 On

I had the same problem in V4 and had to resolve it another way.

The parent <ThemeProvider> with no theme prop solution wouldn't work with Typescript because the theme prop is required.

If anyone needs a solution that works with Typescript, I resolved it using StylesProvider. By wrapping each ThemeProvider in a StyleProvider with a different seed, your theme will no longer interfere with any other components outside of the StyleProvider. Like so

import { ThemeProvider, StylesProvider } from '@material-ui/core/styles';
//...
 <StylesProvider generateClassName={generateClassName}>
      <ThemeProvider theme={theme}>
        <children>
      </ThemeProvider>
  </StylesProvider>

You'll want to create a generateClassName prop to pass in:

import { createGenerateClassName } from '@material-ui/core';

const generateClassName = createGenerateClassName({
  seed: 'blue-select,
});

export default generateClassName;