[javascript] React Js conditionally applying class attributes

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?

The answer is


Replace:

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

with:

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

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(" ")} />

you can simply do the following for example.

let currentDir = i18n && i18n.language ? i18n.language == 'en' ? "ml" : "mr" : "ml";

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

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'}`}>

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.


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


In case you will need only one optional class name:

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

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

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>
    );
  }
});

You can use here String literals

const Angle = ({show}) => {

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

   return <i className={angle} />
}

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'}`}>

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(' ')}/>

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.


<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.

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

Above written as a function:

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

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

_x000D_
_x000D_
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')  )
_x000D_
_x000D_
_x000D_


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">

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;

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( ([k,v]) => v?k:'' ).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

declare helper element and used it 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; 
}


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


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(' ')}>

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"

you can use this:

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

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to twitter-bootstrap-3

bootstrap 4 responsive utilities visible / hidden xs sm lg not working How to change the bootstrap primary color? What is the '.well' equivalent class in Bootstrap 4 How to use Bootstrap in an Angular project? Bootstrap get div to align in the center Jquery to open Bootstrap v3 modal of remote url How to increase Bootstrap Modal Width? Bootstrap datetimepicker is not a function How can I increase the size of a bootstrap button? Bootstrap : TypeError: $(...).modal is not a function

Examples related to reactjs

Error: Node Sass version 5.0.0 is incompatible with ^4.0.0 TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app Template not provided using create-react-app How to resolve the error on 'react-native start' Element implicitly has an 'any' type because expression of type 'string' can't be used to index Invalid hook call. Hooks can only be called inside of the body of a function component How to style components using makeStyles and still have lifecycle methods in Material UI? React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release

Examples related to class-attributes

React Js conditionally applying class attributes