Как добавить несколько классов в компонент ReactJS

196

Я новичок в ReactJS и JSX, и у меня возникла небольшая проблема с кодом ниже.

Я пытаюсь добавить несколько классов в атрибут classNames для каждого li:

<li key={index} className={activeClass, data.class, "main-class"}></li>

Мой компонент React:

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 &amp; Support &nbsp; <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"));
  • 0
    Я нашел краткий ответ здесь stackoverflow.com/a/36209517/4125588 , просто используйте JavaScript, чтобы объединить эти классы, статические или динамические, с оператором «+», не забудьте вставить «» перед классами, кроме первого, в качестве реального класс в HTML должен быть похож на 'ab c', а также пробел между ними.
  • 0
    Возможный дубликат передачи в именах классов для реагирования компонентов
Теги:
ecmascript-6
react-jsx

18 ответов

131
Лучший ответ

Я использую classnames. Например:

...
    var liClasses = classNames({
      'main-class': true,
      'activeClass': self.state.focused === index
    });

    return (<li className={liClasses}>{data.name}</li>);
...
  • 0
    Вы должны импортировать это?
  • 4
    @esilva Вы, конечно, можете
Показать ещё 4 комментария
202

Я использую ES6 шаблона ES6. Например:

const error = this.state.valid ? '' : 'error'
const classes = 'form-control round-lg ${error}'

А затем просто сделать это:

<input className={classes} />

Однолинейная версия:

<input className={'form-control round-lg ${this.state.valid ? '' : 'error'}'} />
  • 112
    Также: <input className={`class1 ${class2}`}>
  • 1
    @unyo Пожалуйста, оставьте свой комментарий в качестве ответа, чтобы я мог проголосовать за него. Это так много заслуживает. Я искал 1 час для чего-то столь же легкого, как это, и теперь я нахожу это похороненным как комментарий. Спасибо.
Показать ещё 4 комментария
93

Просто используйте JavaScript.

<li className={[activeClass, data.klass, "main-class"].join(' ')} />

Если вы хотите добавить ключи и значения на основе классов в объект, вы можете использовать следующее:

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

Или даже проще:

const isEnabled = true;
const isChecked = false;

<li className={[isEnabled && 'enabled', isChecked && 'checked']
  .filter(e => !!e)
  .join(' ')
} />
// Output:
// <li className={'enabled'} />
  • 0
    Вот строка, которая работает для меня: className={['terra-Table', medOrder.resource.status]}
  • 0
    @ DougWilhelm Я не думаю, что это работает. Он неявно вызывает toString и создает список классов через запятую. github.com/facebook/react/issues/3138
Показать ещё 1 комментарий
61

Concat

Не нужно фантазировать Я использую модули CSS, и это легко

import style from '/css/style.css';

<div className={style.style1+ ' ' + style.style2} />

Это приведет к:

<div class="src-client-css-pages-style1-selectionItem src-client-css-pages-style2">

Другими словами, оба стиля

  • 1
    Это сработало для меня, наряду с именами '-', т.е.: <nav className = {styles.navbar + "" + styles ['navbar-default']}>
  • 0
    LOL, я ломаю голову, и ответ простой конкат: D. Кстати, эта работа также работает с модулем CSS Loader.
Показать ещё 3 комментария
22

Это может быть достигнуто с помощью литералов шаблона ES6:

<input className={'class1 ${class2}'}>
22

Вы можете создать элемент с несколькими именами классов, например:

<li className="class1 class2 class3">foo</li>

Естественно, вы можете использовать строку, содержащую имена классов, и манипулировать этой строкой для обновления имен классов элемента.

var myClassNammes = 'class1 class2 class3';
...
<li className={myClassNames}>foo</li>
  • 1
    Вы проверяли это? Я сделал :)
  • 0
    Да, я сделал. На самом деле, я использую его довольно часто, но только что увидел и исправил опечатку. Конечно, строка, содержащая имена классов в первой строке, должна быть сделана с использованием " вместо ' . Извините за это.
15

Вот как вы можете это сделать с ES6:

className = {`
      text-right
      ${itemId === activeItemId ? 'active' : ''}
      ${anotherProperty === true ? 'class1' : 'class2'}
`}

Вы можете перечислить несколько классов и условий, а также включить статические классы. Нет необходимости добавлять дополнительную библиотеку.

Удачи;)

  • 0
    Это приводит к очень уродливому HTML, учитывая все лишние пробелы.
  • 1
    Не надо так писать. Это всего лишь пример, который лучше объясняет решение. И всегда в производстве у вас есть уменьшенная версия :)
10

Vanilla JS

Нет необходимости в внешних библиотеках - просто используйте ES6 строки шаблона:

<i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>
  • 0
    Vanilla JS - это не ES6. Но мне нравится твой пример.
  • 2
    @RyanNerd Вы имеете в виду "ES6 не ванильный JS"? Так или иначе, потому что vanilla js означает javascript без каких-либо рамок. ES6 является более новой версией javascript. - stackoverflow.com/a/20435685/5111113
7

Возможно, classnames может вам помочь.

var classNames = require('classnames');
classNames('foo', {'xx-test': true, bar: false}, {'ox-test': false}); // => 'foo xx-test'
4

Просто добавив, мы можем отфильтровать пустые строки.

className={[
    'read-more-box',
    this.props.className,
    this.state.isExpanded ? 'open' : 'close',
].filter(x => !!x).join(' ')}
3

Поздно к партии, но зачем использовать стороннюю сторону для такой простой проблемы?

Вы могли бы либо сделать это, как упомянул @Huw Davies - лучший способ

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

Оба хороши. Но писать может стать сложным для большого приложения. Чтобы сделать его оптимальным, я делаю то же самое выше, но помещаю его в класс помощника

Используя мою вспомогательную функцию ниже, я могу оставить логику отдельной для будущего редактирования, а также дает несколько способов добавить классы

classNames(styles['foo-bar-baz], 'fa fa-user', 'fa-2x')

или

classNames([styles['foo-bar-baz], 'fa fa-user', 'fa-2x'])

Это моя вспомогательная функция ниже. Я поместил его в helper.js, где храню все свои общие методы. Будучи такой простой функцией, я избегал использования сторонней стороны, чтобы держать контроль

export function classNames (classes) {
    if(classes && classes.constructor === Array) {
        return classes.join(' ')
    } else if(arguments[0] !== undefined) {
        return [...arguments].join(' ')
    }
    return ''
}
2

Если вы не хотите импортировать другой модуль, эта функция работает как модуль classNames.

function classNames(rules) {
    var classes = ''

    Object.keys(rules).forEach(item => {    
        if (rules[item])
            classes += (classes.length ? ' ' : '') + item
    })

    return classes
} 

Вы можете использовать это так:

render() {
    var classes = classNames({
        'storeInfoDiv': true,  
        'hover': this.state.isHovered == this.props.store.store_id
    })   

    return (
        <SomeComponent style={classes} />
    )
}
1

Использование facebook Пример TodoTextInput.js

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

замена classnames на простой код ванильного js будет выглядеть так:

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} />
    )
  }
0

Я использую React 16.6.3 и @Material UI 3.5.1 и могу использовать массивы в className, такие как className={[classes.tableCell, classes.capitalize]}

Так что в вашем примере следующее будет похоже.

<li key={index} className={[activeClass, data.class, "main-class"]}></li>
0

Я bind classNames с модулем CSS, импортированным в компонент.

import classNames from 'classnames'; 
import * as styles from './[STYLES PATH];
const cx = classNames.bind(styles); 

classnames дает возможность объявить className для элемента React декларативным способом.

например:

<div classNames={cx(styles.titleText)}> Lorem </div>

<div classNames={cx('float-left')}> Lorem </div> // global css declared without css modules
<div classNames={cx( (test === 0) ?
             styles.titleText : 
             styles.subTitleText)}>  Lorem </div> // conditionally assign classes

<div classNames={cx(styles.titleText, 'float-left')}> Lorem </div> //combine multiple classes
0

Просто написанное className={"man woman"} помогло мне добавить несколько классов в компонент React при использовании React с NextJS.

//item.js
<input className={"m w"} type="text" placeholder="type"/>

//o.css
.man{
    background-color: green;
}

.woman{
    height: 20vh;
}

Импорт CSS файлов в js файлы стал возможен благодаря модулю next-css.

0

Что я делаю:

компонент:

const Button = ({ className }) => (
  <div className={ className }> </div>
);

Вызывающий компонент:

<Button className = 'hashButton free anotherClass' />
-1

Я использую rc-classnames пакет.

// ES6
import c from 'rc-classnames';

// CommonJS
var c = require('rc-classnames');

<button className={c('button', {
  'button--disabled': isDisabled,
  'button--no-radius': !hasRadius
})} />

Вы можете добавлять классы в любом формате (Array, Object, Argument). Все правдивые значения из массивов или Аргументы плюс ключи в объектах, которые равны true, объединяются вместе.

например:

ReactClassNames('a', 'b', 'c') // => "a b c"
ReactClassNames({ 'a': true, 'b': false, c: 'true' }) // => "a c"
ReactClassNames(undefined, null, 'a', 0, 'b') // => "a b"

Ещё вопросы

Сообщество Overcoder
Наверх
Меню