I am new to ReactJS and JSX and I am having a little problem with the code below.
I am trying to add multiple classes to the className attribute on each li:
<li key={index} className={activeClass, data.class, "main-class"}></li> My React component is:
var AccountMainMenu = React.createClass({ getInitialState: function() { return { focused: 0 }; }, clicked: function(index) { this.setState({ focused: index }); }, render: function() { var self = this; var accountMenuData = [ { name: "My Account", icon: "icon-account" }, { name: "Messages", icon: "icon-message" }, { name: "Settings", icon: "icon-settings" } /*{ name:"Help & Support <span class='font-awesome icon-support'></span>(888) 664.6261", listClass:"no-mobile last help-support last" }*/ ]; return ( <div className="acc-header-wrapper clearfix"> <ul className="acc-btns-container"> {accountMenuData.map(function(data, index) { var activeClass = ""; if (self.state.focused == index) { activeClass = "active"; } return ( <li key={index} className={activeClass} onClick={self.clicked.bind(self, index)} > <a href="#" className={data.icon}> {data.name} </a> </li> ); })} </ul> </div> ); } }); ReactDOM.render(<AccountMainMenu />, document.getElementById("app-container")); 537 Answers
I use ES6 template literals. For example:
const error = this.state.valid ? '' : 'error' const classes = `form-control round-lg ${error}` And then just render it:
<input className={classes} /> One-liner version:
<input className={`form-control round-lg ${this.state.valid ? '' : 'error'}`} /> 6I use classnames when there is a fair amount of logic required for deciding the classes to (not) use. An overly simple example:
... var liClasses = classNames({ 'main-class': true, 'activeClass': self.state.focused === index }); return (<li className={liClasses}>{data.name}</li>); ... That said, if you don't want to include a dependency then there are better answers below.
10Just use JavaScript.
<li className={[activeClass, data.klass, "main-class"].join(' ')} /> If you want to add classes based keys and values in an object you can use the following:
function classNames(classes) { return Object.entries(classes) .filter(([key, value]) => value) .map(([key, value]) => key) .join(' '); } const classes = { 'maybeClass': true, 'otherClass': true, 'probablyNotClass': false, }; const myClassNames = classNames(classes); // Output: "maybeClass otherClass" <li className={myClassNames} /> Or even simpler:
const isEnabled = true; const isChecked = false; <li className={[isEnabled && 'enabled', isChecked && 'checked'] .filter(e => !!e) .join(' ') } /> // Output: // <li className={'enabled'} /> 5Concat
No need to be fancy I am using CSS modules and it's easy
import style from '/css/style.css'; <div className={style.style1+ ' ' + style.style2} /> This will result in:
<div> In other words, both styles
Conditionals
It would be easy to use the same idea with if's
const class1 = doIHaveSomething ? style.style1 : 'backupClass'; <div className={class1 + ' ' + style.style2} /> ES6
For the last year or so I have been using the template literals, so I feel its worth mentioning, i find it very expressive and easy to read:
`${class1} anotherClass ${class1}` 5This can be achieved with ES6 template literals:
<input className={`base-input-class ${class1} ${class2}`}> (edited for clarity)
3You can create an element with multiple class names like this:
<li className="class1 class2 class3">foo</li> Naturally, you can use a string containing the class names and manipulate this string to update the class names of the element.
var myClassNammes = 'class1 class2 class3'; ... <li className={myClassNames}>foo</li> 2This is how you can do that with ES6:
className = {` text-right ${itemId === activeItemId ? 'active' : ''} ${anotherProperty === true ? 'class1' : 'class2'} `} You can list multiple classes and conditions and also you can include static classes. It is not necessary to add an additional library.
Good luck ;)
3I don't think we need to use an external package for just adding multiple classes.
I personally use
<li className={`li active`}>Stacy</li> or
<li className={`li ${this.state.isActive ? 'active' : ''}`}>Stacy<li> or
<li className={'li ' + (this.state.isActive ? 'active' : '') }>Stacy<li> the second and third one in case you need to add or remove classes conditionally.
3Vanilla JS
No need for external libraries - just use ES6 template strings:
<i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/> 4Generally people do like
<div className={ `head ${style.class1} ${Style.class2}` }><div> OR
<div className={ 'head ' + style.class1 + ' ' + Style.class2 }><div> OR
<div className={ ['head', style.class1 , Style.class2].join(' ') }><div> But you can choose to Create a function to do this job
function joinAll(...classes) { return classes.join(" ") } then call it like:-
<div className={joinAll('head', style.class1 , style.class2)}><div> Maybe classnames can help you.
var classNames = require('classnames'); classNames('foo', {'xx-test': true, bar: false}, {'ox-test': false}); // => 'foo xx-test' 2You could do the following:
<li key={index} className={`${activeClass} ${data.class} main-class`}></li> A short and simple solution, hope this helps.
1First install it:
npm install --save clsx Then import it in your component file:
import clsx from 'clsx'; Then use the imported function in your component:
<div className={ clsx(classes.class1, classes.class2)}> Just adding, we can filter out empty strings.
className={[ 'read-more-box', this.props.className, this.state.isExpanded ? 'open' : 'close', ].filter(x => !!x).join(' ')} You can create an element with multiple class names like this, I tryed these both way, its working fine...
If you importing any css then you can follow this way : Way 1:
import React, { Component, PropTypes } from 'react'; import csjs from 'csjs'; import styles from './styles'; import insertCss from 'insert-css'; import classNames from 'classnames'; insertCss(csjs.getCss(styles)); export default class Foo extends Component { render() { return ( <div className={[styles.class1, styles.class2].join(' ')}> { 'text' } </div> ); } } way 2:
import React, { Component, PropTypes } from 'react'; import csjs from 'csjs'; import styles from './styles'; import insertCss from 'insert-css'; import classNames from 'classnames'; insertCss(csjs.getCss(styles)); export default class Foo extends Component { render() { return ( <div className={styles.class1 + ' ' + styles.class2}> { 'text' } </div> ); } } **
If you applying css as internal :
const myStyle = { color: "#fff" }; // React Element using Jsx const myReactElement = ( <h1 style={myStyle} className="myClassName myClassName1"> Hello World! </h1> ); ReactDOM.render(myReactElement, document.getElementById("app"));.myClassName { background-color: #333; padding: 10px; } .myClassName1{ border: 2px solid #000; }<script src=""></script> <script src=""></script> <div> </div>1for more classes adding
... className={`${classes.hello} ${classes.hello1}`... I know this is a late answer, but I hope this will help someone.
Consider that you have defined following classes in a css file 'primary', 'font-i', 'font-xl'
- The first step would be to import the CSS file.
- Then
<h3 class = {` ${'primary'} ${'font-i'} font-xl`}> HELLO WORLD </h3>would do the trick!
0This seem to work for me
<Link className={[classes.button, classes.buttonFirst]}> 1Late to the party, but why use third party for such a simple problem?
You could either do it as @Huw Davies mentioned - the best way
1. <i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/> 2. <i className={[styles['foo-bar-baz'], 'fa fa-user', 'fa-2x'].join(' ')} Both are good. But writing can become complex for a large app. To make it optimal, I do the same above things but put it in a helper class
Using my below helper function, allows me to keep the logic separate for future editing, and also gives me multiple ways to add the classes
classNames(styles['foo-bar-baz], 'fa fa-user', 'fa-2x') or
classNames([styles['foo-bar-baz], 'fa fa-user', 'fa-2x']) This is my helper function below. I've put it in a helper.js where I keep all my common methods. Being such a simple function, I avoided using 3rd party to keep control
export function classNames (classes) { if(classes && classes.constructor === Array) { return classes.join(' ') } else if(arguments[0] !== undefined) { return [...arguments].join(' ') } return '' } You can use arrays and then join them using space.
<li key={index} className={[activeClass, data.class, "main-class"].join(' ')}></li> This will result in :
<li key={index}></li> Create a function like this
function cssClass(...c) { return c.join(" ") } Call it when needed.
<div className={cssClass("head",Style.element,"black")}><div> Using CSS Modules (or Sass Modules) you can isolate your styling to a specific component too.
"Component-scoped CSS allows you to write traditional, portable CSS with minimal side effects: gone are the worries of selector name collisions or affecting other components’ styles."
import * as styles from "./whatever.module.css" // css version import * as styles from "./whatever.module.scss" // sass version <div className={`${styles.class1} ${styles.class2}`}> INSERT YOUR CODE HERE </div> When I have many varying classes, I have found the following to be useful.
The filter removes any of the null values and the join puts all the remaining values into a space separated string.
const buttonClasses = [ "Button", disabled ? "disabled" : null, active ? "active" : null ].filter((class) => class).join(" ") <button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}> Using facebook's TodoTextInput.js example
render() { return ( <input className={ classnames({ edit: this.props.editing, 'new-todo': this.props.newTodo })} type="text" placeholder={this.props.placeholder} autoFocus="true" value={this.state.text} onBlur={this.handleBlur} onChange={this.handleChange} onKeyDown={this.handleSubmit} /> ) } replacing classnames with plain vanilla js code will look like this:
render() { return ( <input className={` ${this.props.editing ? 'edit' : ''} ${this.props.newTodo ? 'new-todo' : ''} `} type="text" placeholder={this.props.placeholder} autoFocus="true" value={this.state.text} onBlur={this.handleBlur} onChange={this.handleChange} onKeyDown={this.handleSubmit} /> ) } If you don't feel like importing another module, this function works like the classNames module.
function classNames(rules) { var classes = '' Object.keys(rules).forEach(item => { if (rules[item]) classes += (classes.length ? ' ' : '') + item }) return classes } You can use it like this:
render() { var classes = classNames({ 'storeInfoDiv': true, 'hover': this.state.isHovered == this.props.store.store_id }) return ( <SomeComponent style={classes} /> ) } 1import classNames from 'classnames';
Can use multiple classes using comas seperated:
<li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>Can use multiple classes using comas separated with condition:
<li className={classNames(classes.buttonArea, !nodes.length && classes.buttonAreaHidden)}>Hello World</li>
Using array as props to classNames will also work, but gives warning e.g.
className={[classes.tableCellLabel, classes.tableCell]} 1clsx makes this simple!
"The clsx function can take any number of arguments, each of which can be an Object, Array, Boolean, or String."
-- clsx docs on npmjs.com
Import it:
import clsx from 'clsx' Use it:
<li key={index} className={clsx(activeClass, data.class, "main-class")}></li> I used this syntax
<div className={[ "d-inline-flex justify-content-center align-items-center ", withWrapper && `ft-icon-wrapper ft-icon-wrapper-${size}`, wrapperClass, ].join(" ")} > <img className={`ft-icon ft-icon-${size} ${iconClass}`} alt={id} src={icon} /> </div> 1That's what I do:
Component:
const Button = ({ className }) => ( <div className={ className }> </div> ); Calling Component:
<Button className = 'hashButton free anotherClass' /> I am using React 16.6.3 and @Material UI 3.5.1, and is able to use arrays in className like className={[classes.tableCell, classes.capitalize]}
So in your example, the following would be similar.
<li key={index} className={[activeClass, data.class, "main-class"]}></li> 1