reactjsmaterial-uijss

Apply MUI Theme to Created DOM Node


I am a huge fan of React-Material's theming feature and have used it extensively, but today I got stumped. To style popups with the theme, normally I stash the popup (with display: none) in my main component file like this:

function App() {

  return (
    <Fragment>
      <Popup /> // ie here
      <LeftPanel />
      <Map />
    </Fragment>
  );
}

And then my themeProvider wraps the <App/>:

<ThemeProvider theme={theme}>
  <App />
</ThemeProvider>

But now I'm trying to style a popup that is not inside <App/> and not on the DOM on load- I'm returning a node from const node = document.createElement('div'). Instead of the custom theme I created (let's say green for primary palette color), when I try to access theme inside makeStyles, it uses MUI's default theme (ie purple for default main palette color). I've tried exporting the custom createMuiTheme theme object from my index file and passing it to the popup component directly, but it keeps using MUI's default theme, ie:

Popup Button, where I'm trying to access my custom MUI theme:

import React, { FunctionComponent } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';


const useStyles = makeStyles(theme => {
  return {
    text: {
      color: 'white',
      fontSize: theme.typography.pxToRem(14),
    },
    tab: {
      backgroundColor: theme.palette.primary.light
      // This comes back as the default MUI theme :(
    }
  }
});

interface PopupButtonProps { }

export const PopupButton: FunctionComponent<PopupButtonProps> = (props) => {
  const classes = useStyles();
  return (
    <div className={ `${classes.tab} 'custom-popup__view-details pointer'`}>
      <Typography variant='button' classes={{ root: classes.text}}>
        VIEW DETAILS
      </Typography>
    </div>
  );
}

Popup:

const Popup = (props: PopupProps) => {
  const node: HTMLElement = document.createElement('div');

  render(
    <>
      <div className="custom-popup__container">
        <PopupElement text={props.attributes.ServiceName} Icon={ProviderIcon} />
        <PopupElement text={props.attributes.Attribute_1} Icon={AddressIcon} />
        <PopupElement text={props.attributes.Attribute_2} Icon={PhoneIcon} />
      </div>
      <PopupButton />
    </>,
    node
  );
  return node;
}

export default Popup;

Does anyone out there have any ideas as to how to use a specific theme inside a component, ie maybe the useTheme hook to get a specific custom theme into a component?

Versions:
React: 16.13.1
MUI: 4.9.9 (I'll try upgrading to 4.9.11 in the meantime)

Solution

  • Just like you used ThemeProvider around App, you should use ThemeProvider in Popup:

    import theme from "./whereever_you_define_your_theme_using_createMuiTheme";
    
    const Popup = (props: PopupProps) => {
      const node: HTMLElement = document.createElement('div');
    
      render(
        <ThemeProvider theme={theme}>
          <div className="custom-popup__container">
            <PopupElement text={props.attributes.ServiceName} Icon={ProviderIcon} />
            <PopupElement text={props.attributes.Attribute_1} Icon={AddressIcon} />
            <PopupElement text={props.attributes.Attribute_2} Icon={PhoneIcon} />
          </div>
          <PopupButton />
        </ThemeProvider>,
        node
      );
      return node;
    }
    
    export default Popup;