Реагуйте Js умовно застосовуючи атрибути класу


333

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

<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? 'показати': 'приховано'}. Чи роблю тут щось не так?


Ви також можете розглянути reakct-bootstrap , оскільки це абстрагує деякі елементи класу на властивості компонентів, що робить те, що ви намагаєтеся зробити трохи простіше.
Dancrumb

Відповіді:


588

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

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

Відзначте пробіл після "потягніть праворуч". Ви не хочете випадково надавати класу "pull-rightshow" замість "pull-right show". Також дужки повинні бути там.


3
Дякую! Мені довелося його трохи змінити, оскільки чомусь він взагалі не виводив btn-group pull-right. Просто показати або приховати.
apexdodge

Це особливо корисно в певних випадках, коли це classnamesможе бути недоцільним. Якщо у вас є ваша renderфункція і у вас є map, ви можете тільки знати, чи хочете ви додати клас під час його надання, тому ця відповідь для цього цілком корисна.
Дейв Купер

відмінна альтернатива замість того, щоб мати купу умовних шаблонів у вашому візуалізації чи поверненні
devonj

@apexdodge, яку модифікацію вам довелося зробити. У мене те саме питання.
RamY

1
@RamY Один із способів - поставити всі класи всередині умовного this.props.showBulkActions ? 'btn-group pull-right show' : 'btn-group pull-right hidden'). Не елегантно, але це працює.
Ян

87

Як зауважили інші, утиліта назви класів є рекомендованим в даний час підходом до обробки умовних імен класів CSS в ReactJs.

У вашому випадку рішення буде виглядати так:

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

...

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

Як бічну зауваження, я б запропонував вам спробувати уникати використання обох showі hiddenкласів, щоб код міг бути простішим. Швидше за все, вам не потрібно встановлювати клас, щоб щось відображалося за замовчуванням.


11
Не могли б ви детальніше розглянути питання про утиліту classNames, яка є "рекомендованим на даний момент підходом"? Це десь зафіксовано в якомусь добре розглянутому документі про найкращу практику? Або просто щось із уст із вуст навколо Реагуйте і 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

Ви можете використовувати тут Stral literals

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

прошу розширити це, яка умова?
мебіт

умова const = (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.