Home > database >  Can you set body id dynamically in React?
Can you set body id dynamically in React?

Time:06-24

I am trying to implement dark mode in my app.
The idea is to add this to the root element:

  <div id="dark">

And then this in CSS:

#dark {
  background-color: #1A1A2E;
}

And then in Css, customize each dom element by using classes. For example, here I will work on cards:

#dark .card-body {
  background-color: #16213E !important;;
}

#dark .card-header {
  background-color: #0F3460 !important;
}  

Now, this works perfectly fine.
But, with Modals, it does not work. I think it's because Modals are not rendered initially so for some reason the dark style does not apply to them.

What worked though is adding id="dark" to each modal:

#dark .modal-header {
  background-color: #0F3460 !important;
}

#dark .modal-body {
  background-color: #16213E !important;;
}

#dark .modal-footer {
  background-color: #16213E !important;;
}

  <Modal
    // dark doesn't get applied automatically for modals because apparently modals are not rendered in the beginning
    id="dark"
    isOpen={this.state.isModalOpen}
    toggle={this.toggleModal}
  >
    <div className="modal-header">

But, it'll be a pain to apply this to every single modal.


One solution mentioned here:

Modal should be the descendant of a tag which has id="dark". It is loaded by the script right below the script tag and you are trying to put 'dark' id on some div tag and the modal doesn't lie inside it, thus the CSS selector not targeting it.

So, you need to put id="dark" on the body tag.


This solves the modals issue.
But, the problem is in my original implementation of dark mode, I am controlling that id in the root component like this:

  // Root component
  <div id={this.state.should_enable_dark_mode ? "dark" : "default"}>

And should_enable_dark_mode is managed like this:

  manageDarkMode() {
    window.addEventListener("storage", () => {
      console.log("change to local storage!");
      let should_enable_dark_mode = localStorage.darkMode == "true";
      this.setState({
        should_enable_dark_mode,
      });
    });
  }

So the problem with the solution mentioned above is that I couldn't find a way to control the body tag from the react app. And I am not sure if it's a good thing to do.
What do you think I should do?

CodePudding user response:

I see in the comments to your original question that you decided to just modify the body element in the browser DOM, which will probably work fine since the body element is not controlled by React and will likely not be changed by any other code.

I would however like to suggest a few improvements that makes it at bit less dirty:

  • use a data attribute like data-display-mode="dark" as a target for your CSS selectors instead of the ID. IDs are supposed to be stable and other tools and libraries (e.g. UI test tools) might rely on this.

  • use the Modal.container property to attach your Modals to the App element (the React-controlled global parent div defined in your React code, which you can control, not the app-root-div in index.html). Then set your data-display-mode attribute here by React-means. This way you will not bypass the virtual DOM.

  • use CSS custom properties for defining your colors, and then define all dark mode modifications in one place. Don't spread your dark-mode-styling code across multiple class selectors - you will have a hard time maintaining this.

  • Related