React Js conditionally applying class attributes

JavascriptCssTwitter Bootstrap-3ReactjsClass Attributes

Javascript Problem Overview


I want to conditionally show and hide this button group depending on what is passed in from the parent component which looks like this:

<TopicNav showBulkActions={this.__hasMultipleSelected} />

....

__hasMultipleSelected: function() {
  return false; //return true or false depending on data
}

....

var TopicNav = React.createClass({
render: function() {
return (
	<div className="row">
		<div className="col-lg-6">
			<div className="btn-group pull-right {this.props.showBulkActions ? 'show' : 'hidden'}">
			    <button type="button" className="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
				  Bulk Actions <span className="caret"></span>
			    </button>
			    <ul className="dropdown-menu" role="menu">
				  <li><a href="#">Merge into New Session</a></li>
				  <li><a href="#">Add to Existing Session</a></li>
				  <li className="divider"></li>
				  <li><a href="#">Delete</a></li>
			    </ul>
			</div>
		</div>
	</div>
    );
  }
});

Nothing is happening however, with the {this.props.showBulkActions ? 'show' : 'hidden'}. Am I doing anything wrong here?

Javascript Solutions


Solution 1 - Javascript

The curly braces are inside the string, so it is being evaluated as string. They need to be outside, so this should work:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? 'show' : 'hidden')}>

Note the space after "pull-right". You don't want to accidentally provide the class "pull-rightshow" instead of "pull-right show". Also the parentheses needs to be there.

Solution 2 - Javascript

As others have commented, classnames utility is the currently recommended approach to handle conditional CSS class names in ReactJs.

In your case, the solution will look like:

var btnGroupClasses = classNames(
  'btn-group',
  'pull-right',
  {
    'show': this.props.showBulkActions,
    'hidden': !this.props.showBulkActions
  }
);

...

<div className={btnGroupClasses}>...</div>

As a side note, I would suggest you to try to avoid using both show and hidden classes, so the code could be simpler. Most likely, you don't need to set a class for something to be shown by default.

2021 addendum: for performance improvement, you can look into [clsx](https://github.com/lukeed/clsx "GitHub - lukeed/clsx: A tiny (228B) utility for constructing className strings conditionally.") as an alternative.

Solution 3 - Javascript

If you are using a transpiler (such as Babel or Traceur) you can use the new ES6 "template strings".

Here is the answer of @spitfire109, modified accordingly:

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'shown' : 'hidden'}`}>

This approach allows you to do neat things like that, rendering either s-is-shown or s-is-hidden:

<div className={`s-${this.props.showBulkActions ? 'is-shown' : 'is-hidden'}`}>

Solution 4 - Javascript

You can use here String literals

const Angle = ({show}) => {

   const angle = `fa ${show ? 'fa-angle-down' : 'fa-angle-right'}`;

   return <i className={angle} />
}

Solution 5 - Javascript

you can simply do the following for example.

let classNameDependsOnCondtion = i18n.language == 'en' ? "classname" : "";

className={`flex flex-col lg:flex-row list-none ${classNameDependsOnCondtion }`}

OR

className={`flex flex-col lg:flex-row list-none ${i18n.language == 'en' ? "classname" : ""}`}

Solution 6 - Javascript

In case you will need only one optional class name:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? "show" : "")}>

Solution 7 - Javascript

Expending on @spitfire109's fine answer, one could do something like this:

rootClassNames() {
  let names = ['my-default-class'];
  if (this.props.disabled) names.push('text-muted', 'other-class');

  return names.join(' ');
}

and then within the render function:

<div className={this.rootClassNames()}></div>

keeps the jsx short

Solution 8 - Javascript

Or use npm classnames. It is very easy and useful especially for constructing the list of classes

Solution 9 - Javascript

Replace:

<div className="btn-group pull-right {this.props.showBulkActions ? 'show' : 'hidden'}">`

with:

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}

Solution 10 - Javascript

You can use ES6 arrays instead of classnames. The answer is based on Dr. Axel Rauschmayer article: Conditionally adding entries inside Array and object literals.

<div className={[
                 "classAlwaysPresent", 
                 ...Array.from(condition && ["classIfTrue"])
                ].join(" ")} />

Solution 11 - Javascript

2019:

React is lake a lot of utilities. But you don't need any npm package for that. just create somewhere the function classnames and call it when you need it;

function classnames(obj){
  return Object.entries(obj).filter( e => e[1] ).map( e=>e[0] ).join(' ');
}

or

function classnames(obj){
 return Object.entries(obj).map( ([cls,enb]) => enb? cls: '' ).join(' ');
}

example

  stateClass= {
    foo:true,
    bar:false,
    pony:2
  }
  classnames(stateClass) // return 'foo pony'


 <div className="foo bar {classnames(stateClass)}"> some content </div>
Just For Inspiration

declaring helper DOM element and using it native toggle method:

(DOMToken​List)classList.toggle(class,condition)

example:

const classes = document.createElement('span').classList; 

function classstate(obj){
  for( let n in obj) classes.toggle(n,obj[n]);
 return classes; 
}
 

Solution 12 - Javascript

More elegant solution, which is better for maintenance and readability:

const classNames = ['js-btn-connect'];

if (isSelected) { classNames.push('is-selected'); }

<Element className={classNames.join(' ')}/>

Solution 13 - Javascript

you can use this:

<div className={"btn-group pull-right" + (this.props.showBulkActions ? ' show' : ' hidden')}>

Solution 14 - Javascript

This is useful when you have more than one class to append. You can join all classes in array with a space.

const visibility = this.props.showBulkActions ? "show" : ""
<div className={["btn-group pull-right", visibility].join(' ')}>

Solution 15 - Javascript

<div className={['foo', condition && 'bar'].filter(Boolean).join(' ')} />

.filter(Boolean) removes "falsey" values from the array. Since class names must be strings, anything other than that would not be included in the new filtered array.

console.log(  ['foo', true  && 'bar'].filter(Boolean).join(' ')  )
console.log(  ['foo', false && 'bar'].filter(Boolean).join(' ')  )

Above written as a function:

const cx = (...list) => list.filter(Boolean).join(' ')

// usage:
<div className={cx('foo', condition && 'bar')} />

var cx = (...list) => list.filter(Boolean).join(' ')
console.log(  cx('foo', 1 && 'bar', 1 && 'baz')  )
console.log(  cx('foo', 0 && 'bar', 1 && 'baz')  )
console.log(  cx('foo', 0 && 'bar', 0 && 'baz')  )

Solution 16 - Javascript

This would work for you

var TopicNav = React.createClass({
render: function() {

let _myClasses = `btn-group pull-right {this.props.showBulkActions?'show':'hidden'}`;

return (
            ...
            <div className={_myClasses}>
               ...
            </div>
    );
  }
});

Solution 17 - Javascript

Reference to @split fire answer, we can update it with template literals, which is more readable,For reference Checkout javascript template literal

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}>

Solution 18 - Javascript

You can use this npm package. It handles everything and has options for static and dynamic classes based on a variable or a function.

// Support for string arguments
getClassNames('class1', 'class2');

// support for Object
getClassNames({class1: true, class2 : false});

// support for all type of data
getClassNames('class1', 'class2', null, undefined, 3, ['class3', 'class4'], { 
    class5 : function() { return false; },
    class6 : function() { return true; }
});

<div className={getClassNames('show', {class1: true, class2 : false})} /> // "show class1"

Solution 19 - Javascript

Based on the value of this.props.showBulkActions you can switch classes dynamically as follows.

<div ...{...this.props.showBulkActions 
? { className: 'btn-group pull-right show' } 
: { className: 'btn-group pull-right hidden' }}>

Solution 20 - Javascript

I would like to add that you can also use a variable content as a part of the class

<img src={src} alt="Avatar" className={"img-" + messages[key].sender} />

The context is a chat between a bot and a user, and the styles change depending of the sender, this is the browser result:

<img src="http://imageurl" alt="Avatar" class="img-bot">

Solution 21 - Javascript

simply use this approach--

<div className={`${this.props.showActions ? 'shown' : 'hidden'}`}>

this is much more neat and clean.

Solution 22 - Javascript

<div className={"h-3 w-3 rounded-full my-auto " + (index.endDate ==="present"? "bg-green-500":"bg-red-500")}></div>

> Don't Forget to add an extra space after the static class names.

Solution 23 - Javascript

A function to return the correct class based on a param (if present)

  getClass(param){
    let podClass = 'classA'
    switch(param.toLowerCase()){
        case 'B':
            podClass  = 'classB'
            break;
        case 'C':
            podClass  = 'classC'
            break;
    }
    return podClass
}

Now just invoke this function from the div where the corresponding class is to be applied.

 <div className={anyOtherClass + this.getClass(param)}

I successfully used this logic to apply the correct color to my bootstrap table rows.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionapexdodgeView Question on Stackoverflow
Solution 1 - Javascriptspitfire109View Answer on Stackoverflow
Solution 2 - JavascriptDiego VView Answer on Stackoverflow
Solution 3 - JavascriptBertrandView Answer on Stackoverflow
Solution 4 - JavascriptMusaView Answer on Stackoverflow
Solution 5 - JavascriptHasan ZahranView Answer on Stackoverflow
Solution 6 - JavascriptEugene ChybisovView Answer on Stackoverflow
Solution 7 - JavascriptflakyView Answer on Stackoverflow
Solution 8 - JavascriptPencilcheckView Answer on Stackoverflow
Solution 9 - JavascriptAmit AgarwalView Answer on Stackoverflow
Solution 10 - JavascriptTudor MorarView Answer on Stackoverflow
Solution 11 - Javascriptpery mimonView Answer on Stackoverflow
Solution 12 - JavascriptNate BenView Answer on Stackoverflow
Solution 13 - JavascriptAmirBllView Answer on Stackoverflow
Solution 14 - JavascriptkooskoosView Answer on Stackoverflow
Solution 15 - JavascriptvsyncView Answer on Stackoverflow
Solution 16 - JavascriptManoj AmalrajView Answer on Stackoverflow
Solution 17 - JavascriptAkhil AravindView Answer on Stackoverflow
Solution 18 - JavascriptTushar SharmaView Answer on Stackoverflow
Solution 19 - JavascriptVladimir TrifonovView Answer on Stackoverflow
Solution 20 - JavascriptJ CView Answer on Stackoverflow
Solution 21 - JavascriptSuraj AdhikaryView Answer on Stackoverflow
Solution 22 - JavascriptCsAlkemyView Answer on Stackoverflow
Solution 23 - Javascriptprakhar3agrwalView Answer on Stackoverflow