Реагировать 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? 'показать скрытое'}. Я что-то здесь не так делаю?


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

Ответы:


591

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

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

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


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классов, чтобы код мог быть проще. Скорее всего, вам не нужно устанавливать класс, чтобы что-то отображалось по умолчанию.


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'}`}>

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

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 . Это очень просто и полезно, особенно для составления списка классов


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

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

1

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

const visibility = this.props.showBulkActions ? "show" : ""
<div className={["btn-group pull-right", visibility].join(' ')}>

1

Заменить:

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

с участием:

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


0

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.