14

There have been many questions on StackOverflow relating to applying conditional classnames to React components; however, I have not seen a good answer for this particular situation:

I have a basic div that I want to conditionally apply the "is-required" class. Here is my approach:

<div className={`some-class ${isRequired && 'is-required'}`}>

The main issue here is that when isRequired is false, then my compiled HTML code ends up looking like this:

<div class='some-class false'>

Obviously, I could use a ternary operator like this so I can return an empty string instead:

<div className={`some-class ${isRequired ? 'is-required' : ''}`}>

But then in the compiled HTML code there is this extra random space included in the class, which won't cause any rendering issues, but I still don't like it:

<div class='some-class '>

Even still, I could remove the space after "someClass" and include it before "isRequired", but now it's harder to read and feels kind of clunky:

<div className={`some-class${isRequired ? ' is-required' : ''}`}>

I have heard of utilities such as classnames, but I am looking for a simple solution where I don't need any additional packages.

What is the recommended approach here?

Drew Jex
  • 845
  • 2
  • 13
  • 24

6 Answers6

8

Actually, there are many ways to do that, here's one of them.

<div className={isRequired ? 'some-class is-required': 'some-class'}>

or you can return null

<div className={isRequired ? 'is-required' : null}>

In order, if you have several classes.

<div className={isRequired ? 'some-class is-required': isDisabled ? 'some-disabled-class' : 'some-class'}>

https://reactjs.org/docs/conditional-rendering.html

class App extends React.Component {

  constructor() {
    super();
    this.state = {
      isRequired: false
    };
}

  render() {
    return (
      <div className="App">
       <div className={this.state.isRequired ? 'is-required' : null}>Null</div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'></div>
Liam
  • 6,517
  • 7
  • 25
  • 47
  • Wouldn't empty string be better than null? Not sure what null would produce. – HMR May 16 '18 at 17:55
  • 1
    It would produce nothing if I used an empty string it would produce a space. – Liam May 16 '18 at 17:56
  • 4
    Must be a React thing then because `new String(null)+"" ` produces "null" for me so would be `
    – HMR May 16 '18 at 18:00
  • What about a situation where I have several classes I want to conditionally apply? So kind of like this: `${isRequired && 'is-required'} ${isDisabled && 'is-disabled'}`. – Drew Jex May 16 '18 at 18:01
  • 1
    @DrewJex assuming that isRequired and isDisabled is an empty string then do your some-class first and all optional classes with a leading space after that: ${isRequired && " is-required"} – HMR May 16 '18 at 18:03
  • @HMR yes you are right it's returning a null as well, I just fixed them – Liam May 16 '18 at 18:19
4

Maybe you'll find this utility function helpful (it will be used as a tagged template):

const c = (strings = [], ...classes) => {
  let myClass = '';
  strings.forEach((s, i) => {
    myClass += s + (classes[i] || '');
  });

  return myClass.trim().replace('  ', ' ');
}

Now you can use it like this :

className={c`my-class ${this.props.done && 'done'} selected`}

or

className={c`some-class ${isRequired && 'is-required'} ${isDisabled && 'some-disabled-class'}`}
Mohamed Ramrami
  • 12,026
  • 4
  • 33
  • 49
2

You can use it if you don't want false value.

<div className={`some-class${isRequired && ' is-required' || ''}`}>
1
<div className={isRequired && 'is-required'}>Required</div>

Using evaluation short circuiting (https://en.wikipedia.org/wiki/Short-circuit_evaluation)

0

I highly recommend using this package for joining class names if you are using an import/export system.

https://www.npmjs.com/package/classnames

Con Antonakos
  • 1,735
  • 20
  • 23
0

className={`rounded-lg ${isActive ? "bg-violet-600" : > "bg-slate-600"}`}>

There are three classes here:

  1. rounded-lg
  2. bg-violet-600
  3. bg-slate-600

Note:

  • I want to appy rounded-lg always
  • And if isActive true, select bg-violet-600 otherwise bg-slate-600
Rohit Kumar
  • 983
  • 9
  • 11