1

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?

1

2 Answers 2

1

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>
);
2
  • Thank you for the detailed description and the propositions @Dyo
    – Sokratis V
    Commented Feb 12, 2018 at 15:24
  • @SokratisV Please note there's a lot of different ways to style your component, there's also tons of JS style libraries to do this but if this kind of computed style is pretty rare you can handle it this way to not depend on an external library.
    – Dyo
    Commented Feb 12, 2018 at 15:46
1

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} />

Not the answer you're looking for? Browse other questions tagged or ask your own question.