Реагировать 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.