Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically load .css based on condition in reactJS application

Tags:

css

reactjs

I have a reactJS application that I want to make available to multiple clients. Each clients has unique color schemes. I need to be able to import the .css file that corresponds to the specific client.

For example, if client 1 logs into the application, I want to import client1.css. if client 2 logs into the application, I want to import client2.css. I will know the client number once I have validated the login information.

The application contains multiple .js files. Every .js file contains the following at the top of the file

import React from 'react';
import  { Redirect } from 'react-router-dom';
import {mqRequest} from '../functions/commonFunctions.js';
import '../styles/app.css';

Is there a way to import .css files dynamically for this scenario as opposed to specifying the .css file in the above import statement?

Thank you

like image 677
Jonathan Small Avatar asked Jun 09 '26 22:06

Jonathan Small


2 Answers

Easy - i've delt with similar before.

componentWillMount() {
  if(this.props.css1 === true) {
     require('style1.css');
  } else {
     require('style2.css');
  }

}

like image 109
Harmenx Avatar answered Jun 12 '26 12:06

Harmenx


A bit late to the party, I want to expand on @Harmenx answer.

require works in development environments only, once it goes to production you're likely to get errors or not see the css file at all. Here are some options if you, or others, encounter this:

Option 1: Using css modules, assign a variable of styles with the response from the import based on the condition.

  let styles;

  if(this.props.css1 === true) {
     //require('style1.css');
     import("./style1.module.css").then((res) => { styles = res;});
  } else {
     //require('style2.css');
     import("./style2.module.css").then((res) => { styles = res;});
  }

  ...
  <div className={styles.divClass}>...</div>
  ...

Option 2: using Suspend and lazy load from react

// STEP 1: create components for each stylesheet
// styles1.js
import React from "react";
import "./styles1.css";

export const Style1Variables = (React.FC = () => <></>);
export default Style1Variables ;

// styles2.js
import React from "react";
import "./styles2.css";

export const Style2Variables = (React.FC = () => <></>);
export default Style2Variables ;

// STEP 2: setup your conditional rendering component
import React, {lazy, Suspense} from "react";
  
const Styles1= lazy(() => import("./styles1"));
const Styles2= lazy(() => import("./styles2"));

export const ThemeSelector = ({ children }) => {
    return (
        <>
            <Suspense fallback={null} />}>
                {isClient1() ? <Styles1 /> : <Styles2/>}
            </Suspense>
            {children}
        </>
    );
};

// STEP 3: Wrap your app
ReactDOM.render(
        <ThemeSelector>
            <App />
        </ThemeSelector>,
    document.getElementById('root')
);

Option 3: Use React Helm which will include a link to the stylesheet in the header based on a conditional

class App extends Component {
  render() {
    <>
      <Helmet>
        <link
          type="text/css"
          rel="stylesheet"
          href={isClient1() ? "./styles1.css" : "./styles2.css"}
      />
      </Helmet>
      ...
    </>
  }
}

Personally, I like option 2 because you can set a variable whichClientIsThis() then modify the code to:

import React, {lazy, Suspense} from "react";

let clientID = whichClientIsThis();
  
const Styles= lazy(() => import("./`${clientID}`.css")); // change your variable filenames to match the client id.

export const ThemeSelector = ({ children }) => {
    return (
        <>
            <Suspense fallback={null} />}>
                <Styles />
            </Suspense>
            {children}
        </>
    );
};

ReactDOM.render(
        <ThemeSelector>
            <App />
        </ThemeSelector>,
    document.getElementById('root')
);

This way you don't need any conditionals. I'd still recommend lazy loading and suspending so the app has time to get the id and make the "decision" on which stylesheet to bring in.

like image 27
mezzomix Avatar answered Jun 12 '26 11:06

mezzomix



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!