Search code examples
reactjscss-modulesdynamic-import

Dynamic imports: importing a css module depending


I would like to import dynamically a css module depending on a prop that is passed through the component

My js file is a like this

import css from './MenuItem.module.styl'
/* .... */
const MenuItem = ({ node, isTitle, isHeader, pathname, hoveredItem }) => {      

  const linkClasses =
    classNames(css.someClass, {[css.someOtherClass]: isHeader})

  const subItemsContainerClasses = classNames(css.someClass, {[css.someOtherClass]: isHeader})

  const itemsContainerClasses = classNames(css.someClass, {[css.someOtherClass]: isHeader})



  return (
    <div className={itemsContainerClasses}>
      /* etc */
    </div>
  )
}

It is getting really messy so I would like to import a different css module depending on the isHeader prop

How and where would I do that? It should be inside the component but if I useEffect, how would I reference the css part

Edit:

I tried this

useEffect(() => {
    if (isheader) {
      import css from './MenuItemHeader.module.styl'
    } else {
      import css from './MenuItemFooter.module.styl'
    }
  });

but I get an error that import statements should be at the begging of the file

And I tried

const [css, setCss] = useState({});

useEffect(() => {
    if (isHeader) {
      import('./MenuItemHeader.module.styl')
        .then((response) => {                    
          setCss(response) 
        })
    } else {    
      import('./MenuItemFooter.module.styl')
        .then((response) => {                    
          setCss(response) 
        })
    }
  });

And I get no errors but the styles are not applied


Solution

  • You can try this

    import  firstCssModule from './MenuItem.firstModule.styles';
    import  secondCssModule from './MenuItem.secondModule.styles';
    
    /* ... */
    
    const resolvedStyle = isHeader ? firstCssModule.someClass : secondCssModule.someClass;
    

    classnames

    const firstClasses =
        classNames(firstCssModule.someClass, {[firstCssModule.someOtherClass]: isHeader})
    
    const secondClasses = classNames(secondCssModule.someClass, {[secondCssModule.someOtherClass]: isHeader})
    
    const mixedClasses = classNames(firstCssModule.someClass, {[secondCssModule.someOtherClass]: isHeader})
    

    Dictionary and calculated properties

    const styles = {
      first: firstCssModule,
      second: secondCssModule
    }
    
    const currentModule = 'first';
    
    styles[currentModule].someClass
    styles[currentModule].someOtherClass
    

    With classnames you can hace something like this and it's ok.

    { [styles[currentModule].someOtherClass]: isHeader }
    

    Validation

    const getStyles = moduleName => {
      if (moduleName in styles) {
        return styles[moduleName];
      } else {
        /* moduleName doesn't exist, do something
    (for example, return default or throw an error) */
        return styles.first; // default
      }
    
    /* ... */
    
    getStyles(currentModule).someClass;
    

    classnames in this case:

    { [getStyles(currentModule).someOtherClass]: isHeader }