How can I dynamically assign a className in a React component based on the current state when importing styles?

I've been utilizing the style-loader to insert CSS modularly into my components ({style.exampleClassName}).

My goal is to showcase a loader for a specific duration before displaying an image (at least 16 of these components in a grid layout).

This is what my current component structure looks like:

// Child Component

/**
*
* Initializes props for the child (icon)
*
*/

import React, { Component } from 'react';
import styles from './styles.css';

class Child extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      hidden : "shown",
      loading: "loading"
    };
  }

  componentDidMount() {
    const self = this;
    const wait = this.props.wait;

    console.log('mounted');
    setTimeout(() => {
      console.log('timeout working ' + wait);
      self.setState({
        hidden: "hidden",
        loading: "loaded"
      });
    }, wait);
  }


  render() {

    const hidden = `styles.${this.state.hidden}`;
    const loading = `styles.${this.state.loading}`;

      return (
        <div>
        <link rel="stylesheet" type="text/css" href="./app/components/socialgrid/styles.css" />
          <div className={this.state.hidden}>
              <p>Loading...</p>
          </div>
          <div className={this.state.loading}>
              <p>Child - {this.props.wait}ms</p>
          </div>
        </div>
      )
  }

};

export default Child;


// Parent

/**
*
* Individual Icon Component
*
*/

import React, { Component } from 'react';
import cx from 'classnames';
import Img from 'components/Img';
import Child from './Child';

// import Fb from './Fb.png';

class IndIcon extends React.Component{
  render() {
    return (
      <div>
        <div>
<Child wait={1000} />
<Child wait={5000} />
<Child wait={4000} />
        </div>
      </div>
    )
  }
};


export default IndIcon;
.hidden,
.loading{
  display: none;
}

Normally, my styles would automatically apply themselves through className={styles.exampleClassName}, but I'm encountering an issue here where the class doesn't get applied because it changes based on state (as mentioned earlier, just trying different phrasing to clarify).

I wish to assign more than just the display:none property, therefore classes are necessary for these components.

Your assistance is greatly appreciated. Thank you!

Answer №1

It appears that you were close to the solution, but you forgot to pass your const variables into your JSX. Make adjustments to your render function as shown below (changes in bold):

render() {
    const hidden = `styles.${this.state.hidden}`;
    const loading = `styles.${this.state.loading}`;

      return (
        <div>
        <link rel="stylesheet" type="text/css" href="./app/components/socialgrid/styles.css" />
          <div className={<b>{hidden}</b>}>
              <p>Loading...</p>
          </div>
          <div className={<b>{loading}</b>}>
              <p>Child - {this.props.wait}ms</p>
          </div>
        </div>
      )
  }

Tip: Embedding styles directly within the component can lead to conflicts with global CSS and cause unexpected styling issues. It's advisable to manage your styles carefully to avoid errors.

Answer №2

Although my initial instinct was to update the classes on state change, I decided to take a different approach and found it to be much more effective:

import React, { Component } from 'react';
import Spinner from './Spinner';
import Icon from './Icon';

class Child extends React.Component {

  constructor(props){
  super(props);

    this.state = {
    loading: true
    }
  }

  componentDidMount(){
    const wait = this.props.wait;

  setTimeout(() => {
    this.setState({
        loading: false
      })
    }, wait)
  }

  render() {

    let content = this.state.loading ?
    <div><Spinner /></div> :
    <div><Icon /></div>;

    return (
    <div>{content}</div>
    )
  }

};

This method allows components to load based on state changes and a settimeout.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

halt execution of npm test and erase any printed content

When I run npm test on my React project, it runs unit tests using jest and react testing library. The test logs (including console log lines added for debugging) are printed to the screen but get deleted after running the tests. It seems like the logs are ...

The Vue.js component appears to be hidden within the Swal.fire HTML

Here is how I use Swal.Fire in my file1.js: import TextModuleComponent from "../components/TextModuleComponent"; export default { components: {TextModuleComponent} } Swal.fire({ title: 'Sending the offer via email?', ...

What could be causing a full-width image render in Firefox when a nested flex item is centered?

My design involves nested containers with the display: flex; property. While Chrome/Edge display the item div correctly, in Firefox 110.0.1 the item div expands to fill the entire horizontal space within the wrapper (100% width). Which CSS properties can ...

Transforming the typical click search into an instantaneous search experience with the power of Partial

I am working on a form that, when the user clicks a button, will display search results based on the entered searchString. @using (Html.BeginForm("Index", "Search")) { <div id="search" class="input-group"> @Html.TextBox("searchString", n ...

Is it possible to utilize Angular's $http.get method with a dynamic route

I recently started working with Angular and I'm trying to figure out how to retrieve data from a REST API using a scope variable to determine the URI for the GET request. Imagine that I have an array of numbers being generated by a service in my app ...

The DOM is failing to refresh in Vue.js even after the array has been updated

After receiving a list of items using AJAX, I store them in a data Array: loadSparepartFiles: function() { var vm = this; vm.activeSparepart.attachments = []; ajaxApi.loadJson('spareparts/sparepart/getFiles/'+vm.activeSparepartId, fu ...

What is the most effective method for fetching images from MongoDB?

I'm currently working on a web application that uses MongoDB's GridFS to store and retrieve images. However, I'm facing an issue where retrieving images from the database takes significantly longer than expected when a user makes a request. ...

How to position a static element using CSS

I'm trying to align an image in the center of the screen, but I've run into some trouble. Typically, this is easy by setting the width of a div and using margin: auto;. However, I also need the div to have the position: fixed; property, which see ...

Expanding Issue with Bootstrap Navigation

Hello! I am experiencing an issue with my navbar. The menu collapses, but it does not expand. I have used an example from Bootstrap and made some tweaks, but for some reason, it still doesn't expand properly. Below is the code that I have been workin ...

Increasing the upward motion of the matrix raining HTML canvas animation

Recently, I've been experimenting with the Matrix raining canvas animation here and I was intrigued by the idea of making it rain upwards instead of downwards. However, my attempts to achieve this using the rotate() method resulted in skewing and stre ...

SSI stands for Server Side Includes, a feature that allows

I have multiple versions of the same HTML page, each with only one hidden variable that is different. This variable is crucial for tracking purposes. Now, I am exploring options to rewrite this by incorporating a HTML file with a hidden variable. Here is ...

What is the best combination of tools to use for web development: express with jade/ejs, along with html5, css

As I delve into learning node.js/express, a question arises about how jade/ejs, html, and css work in harmony. Allow me to share my understanding: The application logic is implemented in node.js/express A portion of this logic/variables is injected into ...

Unable to display <div> elements from CSS within the Wordpress Text Widget

Having trouble displaying a <div> from CSS in a Text Widget on Wordpress. <div class=”deffgall-cutlure” ></div> style.css .deffgall-cutlure { display:block; position:relative; width:100px; height:100px; backgrou ...

Experiencing difficulty importing .pem files into Express

Referred to by this previous inquiry which went unanswered: I've stumbled upon something peculiar. Despite my efforts, I am still unable to import my certificate. Every time I attempt to run my Node/express application, it crashes with the same error ...

Exploring an array in Angular 2 using TypeScript

Just starting out with typescript and angular2 and working through some issues. I have a form that needs to display results from an array of changing items, so I don't know the exact index of each result. Here is my scenario: In my form.html file: ...

Is the reordering of items in an Angular JS array causing a malfunction with the first item

It appears that there may be a syntax error present in my code. Within my controller, I have a set of 4 functions: adding a new item, deleting the current item, moving an item backward (up) in the array, and moving an item forward (down) in the array. Al ...

Difficulty altering link hover background color

I'm having trouble changing the hover effect background-color on the tweets of this page: Despite my efforts, all the links except for the latest tweets are working perfectly. What am I missing? Here's what I've been trying... <script& ...

Struggling to access YouTube account via Google sign-in using Puppeteer framework

I am facing an issue with my puppeteer code where I am unable to proceed past the email page after clicking next due to some bot protection by Google advising me to "Try using a different browser...etc". Is there a way to bypass this using puppeteer? I h ...

Issue with MUI Data Grid sorting: Data Grid sortComparator function returning undefined

I'm attempting to organize data with nested values in a data grid, but I keep receiving 'undefined' on the sortComparator of Data Grid Columns. Code: Column Data Setup: { headerName: 'Title', field: `${this.props.type} ...

Using Selenium WebDriver and JavaScript: Enabling Chrome to Download Multiple Files at Once

After scouring through multiple documents for hours like https://www.selenium.dev/documentation/en/webdriver/js_alerts_prompts_and_confirmations/ as well as https://chromedriver.chromium.org/capabilities and I was unsuccessful in finding a solution wit ...