Як додати кілька класів до компонента ReactJS


347

Я новачок у ReactJS та JSX, і у мене є невеликі проблеми з наведеним нижче кодом.

Я намагаюся додати кілька classNameатрибутів для кожного класу 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"));

Тут я знайшов відповідь на шрифт stackoverflow.com/a/36209517/4125588 , просто використовуйте JavaScript, щоб приєднатися до цих класів, статичних або динамічних, з оператором "+", не забудьте вставити "перед класами, крім першого, як реального клас в HTML повинен бути як "ab c", також пробіл між ними.
Fadeoc Khaos


1
Чому не classNames={{foo: true, bar: true, baz: false}}та classNames={["foo", "bar"]}просто працювати ?
Петро В. Морч

Відповіді:


221

Я використовую назви класів, коли існує достатня кількість логіки, необхідної для вирішення класів (не) використання. Надзвичайно простий приклад :

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

    return (<li className={liClasses}>{data.name}</li>);
...

Однак, якщо ви не хочете включати залежність, то нижче є кращі відповіді.


190
Це дуже погано, що вам довелося занести до бібліотеки імен класів лише для того, щоб додати до елемента два класи :(
user959690

4
@ user959690 Це приклад. Ця бібліотека дуже приємна, коли ти багато чого робиш, і ти маєш складну логіку щодо того, коли класи потрібно застосовувати чи ні. Якщо ви робите щось просте, тоді обов'язково використовуйте шаблони, але кожен випадок різний, і читач повинен вибрати правильний інструмент для своєї роботи.
Джек

7
@ user959690 Варто зазначити, що він зараз встановлений NPM під час використання Webpack , щоб import classNames from 'classnames'потім використовувати в компоненті className={classNames(classes.myFirstClass, classes.mySecondClass)} .
Hooligancat

5
Не потрібно використовувати зовнішню бібліотеку, дивіться мою відповідь нижче.
Хью Девіс

1
Бібліотека має й інші переваги: var btnClass = classNames({ btn: true, 'btn-pressed': this.state.isPressed, 'btn-over': !this.state.isPressed && this.state.isHovered }); return <button className={btnClass}>{this.props.label}</button>;
AmitJS94

396

Я використовую 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'}`} />

158
Також:<input className={`class1 ${class2}`}>
Коді Моніз

3
@unyo Будь ласка, опублікуйте ваш коментар як відповідь, щоб я міг його схвалити. Це настільки заслуговує на це. Я шукав 1 годину чогось такого легкого, як це, і тепер я вважаю, що це поховано як коментар. Дякую.
Souvik Ghosh

Це призводить до <input class=" form-control input-lg round-lg" />. Зверніть увагу на додатковий простір на початку. Це дійсно, але некрасиво. Навіть реагувати на FAQ рекомендує інший спосіб або використовувати пакет імен
Nakedible

Я не можу зрозуміти, чому ви імпортуєте бібліотеку (як у прийнятій відповіді), щоб просто встановити деякі класи, які можна встановити, використовуючи Vanilla JavaScript, який у будь-якому разі є більш ефективним, чистішим і читабельним рішенням.
Маркус Парсонс

2
Це правильна відповідь. Використовувати для цього залежність, запропоновану у відповіді "правильний", є надмірним.
TheDarkIn1978

171

Просто використовуйте 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'} />

Ось рядок, який працював на мене:className={['terra-Table', medOrder.resource.status]}
Дуг Вільгельм

1
@DougWilhelm Я не думаю, що це працює. Він неявно викликаєString і створює розділений комами список класів. github.com/facebook/react/isissue/3138
0xcaff

6
Хороша ідея використовувати className={[listOfClasses].join(' ')}це працює для мене дякую!
Ала Еддін JEBALI

98

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

Іншими словами, обидва стилі

Умовні умови

Використовувати ту саму ідею, як і, було б легко

const class1 = doIHaveSomething ? style.style1 : 'backupClass';

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

1
Це працювало для мене разом з іменами '-', тобто: <nav className = {styles.navbar + "" + styles ['navbar-default']}>
Flinkman

LOL, я тріскаю голову, і відповідь проста: "D". Btw це також робота з модулем завантажувача CSS
GusDeCooL

Проблема в тому, що ви не можете мати додаткові класи (якщо їх не визначено, то вони не будуть додані), тому це залежить від того, якщо ви впевнені, що ваш клас не є нульовим (не обов'язковий). У разі необов'язкового немає кращого за помічників класу (). ми можемо використовувати термінал із шаблонами на зразок className={слайдера $ {className? `$ {className} : ''}}` `. Але це багато [Примітка: 'щось' + undefined = 'щось недооцінене'. Js динамічне перетворення.
Мохаммед Аллал

Звичайно, ви можете просто оголосити змінну вище і використовувати її умовно :)
Джеймі Хатбер

42

Цього можна досягти за допомогою літералів шаблонів ES6:

<input className={`class1 ${class2}`}>

1
це майже працювало для мене, я просто повинен був також інтерполювати class1 і більше не буде помилок, так що це виглядає так <input className={`${class1} ${class2}`}>
Kingston Fortune

35

Ви можете створити елемент із кількома іменами класів, як це:

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

Природно, ви можете використовувати рядок, що містить назви класів, і маніпулювати цією рядком для оновлення назв класу елемента.

var myClassNammes = 'class1 class2 class3';
...
<li className={myClassNames}>foo</li>

1
Ви тестували це? Я зробив :)
ворон

Так. Насправді я використовую його досить часто, але просто бачив та виправляв друкарські помилки. Звичайно, рядок, що містить назви класів у першому рядку, повинен бути використаний "замість '. Вибач за те.
nightlyop

20

Ось як це можна зробити за допомогою ES6:

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

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

Удачі ;)


2
Це призводить до отримання дуже некрасивого HTML, враховуючи всю додаткову пробіл.
Голий

2
Не треба так писати. Це лише приклад, який краще пояснить рішення. І завжди у виробництві у вас є мінімізована версія :)
Христо Єфтімов

18

Ваніль JS

У зовнішніх бібліотеках немає потреби - просто використовуйте рядки шаблонів ES6 :

<i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>

Vanilla JS НЕ ES6. Але мені подобається твій приклад.
RyanNerd

8
@RyanNerd Ви маєте на увазі "ES6 - це не ванільний JS"? Так чи інакше, адже vanilla js означає JavaScript без будь-яких фреймворків. ES6 - це новіша версія JavaScript. - stackoverflow.com/a/20435685/5111113
Хью Девіс

Неправильна відповідь, але її можна було б значно покращити. Наприклад, всі інші додавали приклади про держави.
JGallardo

10

Можливо, назви класів можуть вам допомогти.

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

1
Чи можете ви зробити цей приклад більш корисним.
JGallardo

9

Я не думаю, що нам потрібно використовувати зовнішній пакет для додавання кількох класів.

Я особисто використовую

<li className={`li active`}>Stacy</li>

або

<li className={`li ${this.state.isActive ? 'active' : ''}`}>Stacy<li>

другий у випадку, якщо вам потрібно додати або видалити класи умовно.


1
це додасть лише один клас у будь-якому випадку.
TrickOrTreat

6

Тільки додаючи, ми можемо відфільтрувати порожні рядки.

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

6

Ви можете створити елемент з декількома іменами класів, як це, я спробував їх обома способами, його добре працює ...

Якщо ви імпортуєте будь-який css, ви можете слідувати таким чином: Спосіб 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>
    );
  }
}

спосіб 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>
    );
  }
}

**

Якщо ви застосовуєте css як внутрішній:

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="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.production.min.js"></script>
<div id="app">
  
</div>


6

Ви можете зробити наступне:

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

Коротке і просте рішення, сподіваюся, це допоможе.


5

Це можна зробити за допомогою https://www.npmjs.com/package/clsx :

https://www.npmjs.com/package/clsx

Спочатку встановіть його:

npm install --save clsx

Потім імпортуйте його у свій компонентний файл:

import clsx from  'clsx';

Потім використовуйте імпортовану функцію у своєму компоненті:

<div className={ clsx(classes.class1, classes.class2)}>

4

Пізно до вечірки, але навіщо використовувати третю сторону для такої простої проблеми?

Ви можете це зробити так, як згадував @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 ''
}

3

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

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

Це призведе до:

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

3

Я знаю, що це пізня відповідь, але сподіваюся, що це комусь допоможе.

Подумайте, що ви визначили наступні класи у файлі css ' основний ', ' font-i ', ' font-xl '

  • Першим кроком було б імпортувати файл CSS.
  • Тоді

<h3 class = {` ${'primary'} ${'font-i'} font-xl`}> HELLO WORLD </h3>

зробив би трюк!

Для отримання додаткової інформації: https://www.youtube.com/watch?v=j5P9FHiBVNo&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=20



2

Використовуючи приклад TodoTextInput.js у facebook

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

заміна назв класів звичайним кодом 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} />
    )
  }

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

Навіщо використовувати закриття, якщо ви можете зробити те ж саме з картою або зменшити? function classNames(rules) { return Object.entries(rules) .reduce( (arr, [cls, flag]) => { if (flag) arr.push(cls); return arr }, [] ).join(" ") }
Євгеній Савичев

1

Ось що я роблю:

Компонент:

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

Виклик компонента:

<Button className = 'hashButton free anotherClass' />

1

Я використовую 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>

Це те, що я робив (хоч і не MUI) і не працює, застосовується лише для першого класу - без попередження та скарги.
Хуан Ланус

1

Використовуйте https://www.npmjs.com/package/classnames

імпортувати classNames з 'імен класів';

  1. Можна використовувати кілька класів, використовуючи відокремлені комами:

    <li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>
  2. Можна використовувати кілька класів за допомогою коми, розділених умовою:

    <li className={classNames(classes.buttonArea, !nodes.length && classes.buttonAreaHidden)}>Hello World</li> 

Використання масиву як реквізиту для classNames також буде працювати, але попереджає, наприклад

className={[classes.tableCellLabel, classes.tableCell]}


0

Я використовую пакет 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
})} />

Ви можете додавати класи в будь-якому форматі (масив, об’єкт, аргумент). Всі триєдні значення з масивів або аргументів плюс клавіші в об'єктах, рівних для 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"

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

Я зазвичай використовую це так: (у вашому випадку)

    <li  key={index} className={
        "component " +
        `${activeClass? activeClass: " not-an-active-class "}` +
        `${data.class? " " + data.class : " no-data-class "}`
   } />

Якщо мова йде про JSX і (як правило), у нас є деякий json ... ніж ти це циклічний ... компонент . map , а також деякі умовні, щоб перевірити, чи існує властивість json для відображення імені класу залежно від значення властивості від JSON. У наведеному нижче прикладі компонент_кольоровий і компонентний_марк_шард - це властивості компонента компонента.map ()

   <div className={
        "component " +
        `${component_color? component_color: " no-color "}` +
        `${component_dark_shade? " " + component_dark_shade : " light "}`
   }/>

Вихід: <div class="component no-color light" .... Або: <div class="component blue dark" ....залежно від значень з карти ...


0

Коли у мене є багато різних класів, я визнав таке, що є корисним.

Фільтр видаляє будь-яке nullзначення, а з'єднання вводить усі залишилися значення в розділену пробілом рядок.

const buttonClasses = [
    "Button", 
    disabled ? "disabled" : null,
    active ? "active" : null
].filter((class) => class).join(" ")

<button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.