Реагировать Js условно применяя атрибуты класса

334

Я хочу условно показать и скрыть эту группу кнопок в зависимости от того, что передается из родительского компонента, который выглядит следующим образом:

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

Однако ничего не происходит с {this.props.showBulkActions? 'показать скрытое'}. Я что-то здесь не так делаю?

apexdodge
источник
Вы также можете рассмотреть реакцию-бутстрап , так как это абстрагирует некоторые вещи класса в свойства компонентов, делая то, что вы пытаетесь сделать, немного проще.
Данкрамб

Ответы:

591

Фигурные скобки находятся внутри строки, поэтому она оценивается как строка. Они должны быть снаружи, поэтому это должно работать:

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

Обратите внимание на пробел после «тянуть-вправо». Вы не хотите случайно предоставить класс «pull-righthow» вместо «pull-right show». Также скобки должны быть там.

spitfire109
источник
3
Спасибо! Мне пришлось немного изменить его, потому что по какой-то причине он вообще не выводил pull-right в btn-group. Просто показать или спрятать.
apexdodge
Это особенно полезно в определенных случаях, когда это classnamesможет быть нецелесообразно. Если вы находитесь в своей renderфункции и у вас есть map, вы можете знать, хотите ли вы добавить класс во время его рендеринга, поэтому этот ответ весьма полезен для этого.
Дейв Купер
отличная альтернатива вместо того, чтобы иметь кучу условных шаблонов в вашем
рендере
@apexdodge, какую модификацию ты должен был сделать. У меня такая же проблема.
RamY
1
@RamY Один из способов - поместить все классы в условные this.props.showBulkActions ? 'btn-group pull-right show' : 'btn-group pull-right hidden'). Не элегантно, но это работает.
Ян
87

Как прокомментировали другие, в настоящее время рекомендуется использовать утилиту classnames для обработки условных имен классов CSS в ReactJ.

В вашем случае решение будет выглядеть так:

var btnGroupClasses = classNames(
  'btn-group',
  'pull-right',
  {
    'show': this.props.showBulkActions,
    'hidden': !this.props.showBulkActions
  }
);

...

<div className={btnGroupClasses}>...</div>

В качестве примечания, я бы посоветовал вам избегать использования обоих showи hiddenклассов, чтобы код мог быть проще. Скорее всего, вам не нужно устанавливать класс, чтобы что-то отображалось по умолчанию.

Диего V
источник
11
Не могли бы вы уточнить, что утилита classNames является «рекомендуемым в настоящее время подходом»? Это отражено в каком-то известном документе о передовой практике? Или просто из уст в уста вокруг React и classNamesв данный момент?
Александр Нид
6
@anied На момент написания статьи это было рекомендовано в официальной документации React: web.archive.org/web/20160602124910/http://facebook.github.io:80/…
Диего V
3
Он по - прежнему упоминается в последней документации : « Если вы часто писать код , как это, пакет может имена классов упростить его. »
Франклин Ю
66

Если вы используете транспортер (например, Babel или Traceur), вы можете использовать новые ES6 « шаблоны строк ».

Вот ответ @ spitfire109, измененный соответственно:

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

Этот подход позволяет вам делать такие аккуратные вещи, рендеринг s-is-shownили s-is-hidden:

<div className={`s-${this.props.showBulkActions ? 'is-shown' : 'is-hidden'}`}>
Bertrand
источник
20
Будьте осторожны со вторым подходом, особенно в больших кодовых базах, так как он делает строки классов менее понятными. Например, если кто-то ищет s-is-shownили s-is-hiddenв базе кода, он не найдет этот код.
отметка
15

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

const Angle = ({show}) => {

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

   return <i className={angle} />
}
Musa
источник
9

Опираясь на хороший ответ @ spitfire109, можно сделать что-то вроде этого:

rootClassNames() {
  let names = ['my-default-class'];
  if (this.props.disabled) names.push('text-muted', 'other-class');

  return names.join(' ');
}

а затем внутри функции рендеринга:

<div className={this.rootClassNames()}></div>

держит JSX коротким

хлопьевидный
источник
8

Или используйте имена классов npm . Это очень просто и полезно, особенно для составления списка классов

Pencilcheck
источник
8

На случай, если вам понадобится только одно необязательное имя класса:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? "show" : "")}>
Евгений Чибисов
источник
1
Это добавит falseкласс, когда условие не выполнено.
РА.
6

Вы можете использовать массивы ES6 вместо имен классов. Ответ основан на статье доктора Акселя Раушмайера: Условное добавление записей в массив и массивы объектов .

<div className={[
                 "classAlwaysPresent", 
                 ...Array.from(condition && ["classIfTrue"])
                ].join(" ")} />
Тудор Морар
источник
пожалуйста, подробно об этом, в каком состоянии?
Миббит
константное состояние = (1 === 1);
Тудор Морар
5

2019:

Реакция на озеро много полезных. Но вам не нужен npmпакет для этого. просто создайте где-нибудь функцию classnamesи вызывайте ее, когда вам нужно;

function classnames(obj){
  return Object.entries(obj).filter( e => e[1] ).map( e=>e[0] ).join(' ');
}

или

function classnames(obj){
 return Object.entries(obj).map( ([k,v]) => v?k:'' ).join(' ');
}

пример

  stateClass= {
    foo:true,
    bar:false,
    pony:2
  }
  classnames(stateClass) // return 'foo pony'

 <div className="foo bar {classnames(stateClass)}"> some content </div>

Просто для вдохновения

объявить вспомогательный элемент и использовать его toggleметод

(DOMToken​List)classList.toggle(class,condition)

пример:

const classes = document.createElement('span').classList; 

function classstate(obj){
  for( let n in obj) classes.toggle(n,obj[n]);
 return classes; 
}
мимон
источник
4

Более элегантное решение, которое лучше для обслуживания и удобочитаемости:

const classNames = ['js-btn-connect'];

if (isSelected) { classNames.push('is-selected'); }

<Element className={classNames.join(' ')}/>
Нейт Бен
источник
3

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

<div className={"btn-group pull-right" + (this.props.showBulkActions ? ' show' : ' hidden')}>
AmirBll
источник
2

Это будет работать для вас

var TopicNav = React.createClass({
render: function() {

let _myClasses = `btn-group pull-right {this.props.showBulkActions?'show':'hidden'}`;

return (
            ...
            <div className={_myClasses}>
               ...
            </div>
    );
  }
});
Маной Амальрай
источник
1

Вы можете использовать этот пакет npm. Он обрабатывает все и имеет параметры для статических и динамических классов на основе переменной или функции.

// 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"
Тушар Шарма
источник
1

В зависимости от значения this.props.showBulkActionsвы можете динамически переключать классы следующим образом.

<div ...{...this.props.showBulkActions 
? { className: 'btn-group pull-right show' } 
: { className: 'btn-group pull-right hidden' }}>
Владимир Трифонов
источник
1

Я хотел бы добавить, что вы также можете использовать переменное содержимое как часть класса

<img src={src} alt="Avatar" className={"img-" + messages[key].sender} />

Контекст - это чат между ботом и пользователем, и стили меняются в зависимости от отправителя, это результат браузера:

<img src="http://imageurl" alt="Avatar" class="img-bot">
JC
источник
1

Это полезно, когда вам нужно добавить несколько классов. Вы можете объединить все классы в массиве с пробелом.

const visibility = this.props.showBulkActions ? "show" : ""
<div className={["btn-group pull-right", visibility].join(' ')}>
kooskoos
источник
1

Заменить:

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

с участием:

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}
Амит Агарвал
источник
0

Ссылка на @split огнь ответ, мы можем обновить его шаблон литералы, который является более удобным для чтения, для справки Checkout Javascript шаблона буквальных

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}>
Ахил аравинд
источник
0

Я нашел это, которое объясняет, как сделать это с троичной и с библиотекой классов

Чачан
источник