In this article we will see how to generate dynamic classes for React without resorting to obnoxious string manipulations.

We will build a simple app that changes the color and font-style of a div based on a textbox value.

The rules

The text in our div should be:

  • Red when the value is negative
  • Blue when the value is positive
  • Italic when the value is even
  • Normal when the value is odd

Corresponding css classes:

.blue {
color: blue;
}

.red {
color: red;
}

.italic {
font-style: italic;
}

.normal {
font-style: normal;
}

The magic

React now uses the classNames library to join and manage class names.

You can install it with npm or bower.

The classNames library allows you to declare your classes as a string, an array or an object. The 3 following declarations are equivalent:

String

var elementClass = className('red italic');

Array

var elementClass = className(['red', 'italic']);

Object

var elementClass = className({
red: true, // use true or any truthy value / expression
italic: true
});

Note:

You can even use a mix of all three as separate parameters:

var elementClass = className("class1 class2", // String
['class3', 'class4'], // Array
{class5: true}); // Object

It will add all 5 classes to the element.

The example

Rendering the elements

Let’s start with the render function. We will need a div with some text and a text input:

render: function() {
return (
<div>
<div className={this.state.textClass}>RESULT</div>
<input type="text" value="Hello!" value={this.state.value} onChange={this.handleChange} />
</div>
)
}
  • this.state.value: will hold the number we are going to check
  • this.state.textClass: will hold our classes generated with className
  • this.handleChange: will regenerate the classes when the textbox value changes

Generating our css classes

We can now create our class generation function based on the example defined above:

computeClass: function(val) {
return classNames({
blue: val > 0, // positive -> blue
red: val < 0, // negative -> red
italic: val % 2 === 0, // even -> italic
normal: Math.abs(val % 2) === 1 // odd -> normal
});
}

Consider always using this method in your applications. Conditional blocks used to generate strings are a hell to read and maintain ;)

Full React code

var Main = React.createClass({
getInitialState: function() {
return {
value: 0,
textClass: this.computeClass(0)
};
},
computeClass: function(val) {

return classNames({
blue: val > 0,
red: val < 0,
italic: val % 2 === 0,
normal: Math.abs(val % 2) === 1
});
},
handleChange: function(event) {

var val = isNaN(event.target.value) ? 0 : event.target.value,
textClass = this.computeClass(val);

this.setState({value: val, textClass: textClass});
},
render: function() {
return (
<div>
<div className={this.state.textClass}>RESULT</div>
<input type="text" value="Hello!" value={this.state.value} onChange={this.handleChange} />
</div>
)
}
});

ReactDOM.render(<Main />, document.getElementById("main"));

Or check it live here: https://jsbin.com/kijica/edit?html,output