0

I have 2 components in my react app for now: App and Navbar I am trying to dynamically load css (4 different themes from bootswatch) on user click (theming in short)

Below are the components:

App.js

class App extends Component {
  state = {};
  availableThemes = ["lux", "sketchy", "flatly", "darkly"];

  constructor() {
    super();
    this.changeTheme("flatly");
    ReactDOM.findDOMNode;
  }

  changeTheme = themeName => {
    console.log("Theme", themeName);
    if (this.availableThemes.indexOf(themeName) < 0) {
      alert("Theme not available");
    } else {
      import(`./themes/${themeName}/bootstrap.min.css`)
        .then(() => {
          console.log("Theme loaded", themeName);
        })
        .catch(() => {});
    }
  };

  render() {
    return (
      <NavBar
        themesList={this.availableThemes}
        onThemeChange={this.changeTheme}
      />
    );
  }
}

Navbar.jsx:

class NavBar extends Component {
  state = {};
  render() {
    const { themesList, onThemeChange } = this.props;

    return (
      <Navbar bg="dark" variant="dark" expand="lg">
        <Navbar.Brand>WiLite</Navbar.Brand>
        <Navbar.Collapse style={{ paddingLeft: 25 + "%" }}>
          <Form inline>
            <FormGroup>
              <FormControl
                type="text"
                placeholder="Search"
                className="mr-sm-2"
              />
              <Button variant="outline-light">Search</Button>
            </FormGroup>
          </Form>
          <Nav>
            <NavDropdown title="Theme">
              {themesList.map(theme => {
                return (
                  <NavDropdown.Item
                    key={v4()}
                    onClick={() => {
                      onThemeChange(theme);
                    }}
                  >
                    {theme}
                  </NavDropdown.Item>
                );
              })}
            </NavDropdown>
          </Nav>
        </Navbar.Collapse>
      </Navbar>
    );
  }
}

Now the output of changeTheme is very random. Sometimes the theme gets applied, sometimes it doesn't and sometimes I get a mixture of both the themes (the one I requested and the one which was already loaded).

Can someone please suggest how can I accomplish this?

  • You need to remove the previously imported file. Check this out https://stackoverflow.com/questions/54078728/unload-remove-dynamically-loaded-css-files . Use `link` elements so you can remove them afterwards. – Mihai T Feb 03 '20 at 12:05
  • It seems legit. But how do I remove the previously imported css? Does creating a new Portal destroy the older one? And if it does then will it not destroy the states of component under it? ```Sorry if the questions are naive, I am new to ReactJS``` – Raja Nand Sharma Feb 03 '20 at 18:56
  • I don't think you need to use Portal. Just use javascript and append/remove `link` elements from `head` of the document. – Mihai T Feb 04 '20 at 08:33
  • Okay let me try that out. Thanks :) – Raja Nand Sharma Feb 04 '20 at 09:28
  • I did it using reactjs. But I ended up adding it in the ```body``` instead of ```head```. I know it is against the HTML syntax and stuff, but will it cause some problems when I put it live on the internet? – Raja Nand Sharma Feb 04 '20 at 11:55
  • `A element can occur either in the or element, depending on whether it has a link type that is body-ok. For example, the stylesheet link type is body-ok, and therefore is permitted in the body. However, this isn't a good practice to follow; it makes more sense to separate your elements from your body content, putting them in the .` from -> https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link . I don't think you will have any problems. – Mihai T Feb 04 '20 at 12:01

0 Answers0