Sokratis V
Sokratis V

Reputation: 101

Conditional rendering of CSS style in elements React

I'm trying to make a signal bar which depending on the number of strength (1-3) will display the corresponding number of bars in black (activated) otherwise in grey colour. So in React i have used the following:

class Application extends React.Component {

  signalBar{
    switch(this.props.signal-strength) {
    case 1:
        < className={{'first-bar, signal-bars, bar'}}  style={{display: 'block', color 'black'}}>
        < className={{'second-bar, signal-bars, bar'}}  style={{display: 'block', color 'grey'}}>
        < className={{'third-bar, signal-bars, bar'}} style={{display: 'block', color 'grey'}}>
        break;
    case 2:
         < className={{'first-bar, signal-bars, bar'}}  style={{display: 'block', color 'black'}}>
          < className={{'second-bar, signal-bars, bar'}}  style={{display: 'block', color 'black'}}>
          < className={{'third-bar, signal-bars, bar'}} style={{display: 'block', color 'grey'}}>
    case 3:
         < className={{'first-bar, signal-bars, bar'}} style={{display: 'block', color 'black'}}>
            < className={{'second-bar, signal-bars, bar'}}  style={{display: 'block', color 'black'}}>
           < className={{'third-bar, signal-bars, bar'}} style={{display: 'block', color 'black'}}>
        break;

    default:

        < className={{'first-bar bar'}}  style={{display: 'block', color 'grey'}}>
        < className={{'second-bar bar'}}  style={{display: 'block', color 'grey'}}>
        < className={{'third-bar bar'}}  style={{display: 'block', color 'grey'}}>    
    }
      }

  render() {

    return <div className={{sizing-box}}>
       <div className={{signal-bars, bar}}>
          {this.signalBar}
        </div>
         </div>
      <p>

      </p>
    </div>;
  }
}


React.render(<Application />, document.getElementById('app'));

CSS:

html, body
  height: 100%

body
  background: #333
  display: flex
  justify-content: center
  align-items: center;     
  { box-sizing: border-box; }

.sizing-box {
  height: 50px;
  width: 80px;
}

.signal-bars {
  display: inline-block;

}

.signal-bars .bar {
  width: 14%;
  margin-left: 1%;
  min-height: 20%;
  display: inline-block;
}
.signal-bars .first-bar  { height: 30%; }
.signal-bars .second-bar { height: 60%; }
.signal-bars .third-bar  { height: 90%; }

The value of signal-strength is not static and can change depending on pros from the parent element. The error i'm getting is 'this is a reserved word'. How can someone inject the function 'signalBar' in a React element? Is there a more 'simple' way to do this with less coding in switch condition?

Upvotes: 1

Views: 12496

Answers (2)

Dyo
Dyo

Reputation: 4464

With inline styles, you can do some computed styles like this :

const colorScheme = {
    first: ['grey', 'black', 'black', 'black'],
    second: ['grey', 'grey', 'black', 'black'],
    third: ['grey', 'grey', 'grey', 'black'],
}
class Application extends React.Component {
  render() {
    const colorNb = ((this.props.signal-strength < 4) && (this.props.signal-strength > 0)) ? this.props.signal-strength : 0;

    return (
       <div className={{sizing-box}}>
          <div className={{signal-bars, bar}}>
             <div className={{'first-bar, signal-bars, bar'}}  style={{display: 'block', color: colorScheme.first[colorNb] }} />
             <div className={{'second-bar, signal-bars, bar'}}  style={{display: 'block', color: colorScheme.second[colorNb] }} />
             <div className={{'third-bar, signal-bars, bar'}} style={{display: 'block', color: colorScheme.third[colorNb] }} /> 
         </div>
     </div>
    );
  }
}

If you have control over your css you can also use the child selector and the inheritance to use less classeNames on your bars :

.signal-bars {
  display: inline-block;
}

.signal-bars div {
  width: 14%;
  margin-left: 1%;
  min-height: 20%;
  display: block;
}
.signal-bars div:nth-child(1)  { height: 30%; }
.signal-bars div:nth-child(2) { height: 60%; }
.signal-bars div:nth-child(3)  { height: 90%; }

Then your component will be cleaner :

return (
   <div className="sizing-box">
       <div className="signal-bars">
           <div style={{ color: colorScheme.first[colorNb] }} />
           <div style={{ color: colorScheme.second[colorNb] }} />
           <div style={{ color: colorScheme.third[colorNb] }} /> 
       </div>
   </div>
);

Upvotes: 1

arthurakay
arthurakay

Reputation: 5651

I like to use the classnames package from npm.

For example:

    <div className={classnames('first-bar', {'signal-bars': this.state.signal-strength === 1})} />

Alternatively you can move all of the logic outside of the DIV itself:

    const divClasses = classnames('first-bar', {
        'signal-bars': this.state.signal-strength === 1
    })
    // ...
    <div className={divClasses} />

Upvotes: 1

Related Questions