Reagisci Js applicando condizionalmente gli attributi di classe


334

Voglio mostrare e nascondere in modo condizionale questo gruppo di pulsanti a seconda di cosa viene passato dal componente genitore che assomiglia a questo:

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

Non succede nulla, tuttavia, con {this.props.showBulkActions? 'show': 'hidden'}. Sto facendo qualcosa di sbagliato qui?


Potresti anche prendere in considerazione la reazione a bootstrap , dal momento che questo estrae alcune delle cose di classe nelle proprietà dei componenti, rendendo ciò che stai cercando di fare un po 'più facile.
Dancrumb,

Risposte:


591

Le parentesi graffe si trovano all'interno della stringa, quindi viene valutata come stringa. Devono essere all'esterno, quindi dovrebbe funzionare:

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

Nota lo spazio dopo "pull-right". Non si desidera fornire accidentalmente la classe "pull-rightshow" anziché "pull-right show". Anche le parentesi devono essere lì.


3
Grazie! Ho dovuto modificarlo leggermente perché per qualche motivo non stava emettendo alcun pull-right del gruppo btn. Mostra o nascosto.
apexdodge,

Ciò è particolarmente utile in alcuni casi in cui classnamespotrebbe non essere appropriato. Se sei nella tua renderfunzione e ne hai una map, potresti solo sapere se vuoi aggiungere una classe nel momento in cui la stai visualizzando, quindi questa risposta è abbastanza utile per questo.
Dave Cooper,

ottima alternativa invece di avere un sacco di modelli condizionali nel tuo rendering o ritorno
devonj,

@apexdodge quale modifica hai dovuto fare. Ho lo stesso problema.
RamY,

1
@RamY Un modo è mettere tutte le classi all'interno del condizionale this.props.showBulkActions ? 'btn-group pull-right show' : 'btn-group pull-right hidden'). Non elegante ma funziona.
Ian

87

Come altri hanno commentato, l' utilità classnames è l'approccio attualmente raccomandato per gestire i nomi di classe CSS condizionali in ReactJs.

Nel tuo caso, la soluzione sarà simile a:

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

...

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

Come nota a margine, ti suggerirei di provare a evitare di usare sia le classi showche le hiddenclassi, quindi il codice potrebbe essere più semplice. Molto probabilmente non è necessario impostare una classe affinché qualcosa venga mostrato per impostazione predefinita.


11
Potresti elaborare l'utilità classNames come "approccio attualmente raccomandato"? È stato catturato in alcuni documenti di buone pratiche ben considerati da qualche parte? O semplicemente una specie di passaparola attorno a React e classNamesal momento?
Alexander Nied,

6
@anied Al momento della stesura di questo documento è stato raccomandato nella documentazione ufficiale di React: web.archive.org/web/20160602124910/http://facebook.github.io:80/…
Diego V

3
È ancora menzionato nell'ultima documentazione : " Se ti ritrovi spesso a scrivere codice in questo modo, il pacchetto classnames può semplificarlo. "
Franklin Yu

66

Se si utilizza un transpiler (come Babel o Traceur) è possibile utilizzare le nuove " stringhe di modelli " ES6 .

Ecco la risposta di @ spitfire109, modificata di conseguenza:

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

Questo approccio ti consente di fare cose ordinate come questa, renderizzando s-is-showno s-is-hidden:

<div className={`s-${this.props.showBulkActions ? 'is-shown' : 'is-hidden'}`}>

20
Fai attenzione con il secondo approccio, specialmente in codebase di grandi dimensioni, poiché rende le stringhe di classe meno greppable. Ad esempio, se qualcuno cerca s-is-showno s-is-hiddennella base di codice, non troverà questo codice.
segna il

15

Puoi usare qui i letterali String

const Angle = ({show}) => {

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

   return <i className={angle} />
}

9

Spendendo la bella risposta di @ spitfire109, si potrebbe fare qualcosa del genere:

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

  return names.join(' ');
}

e quindi all'interno della funzione di rendering:

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

mantiene il jsx corto



8

Nel caso in cui sia necessario un solo nome di classe opzionale:

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

1
Questo aggiungerà falseclasse quando la condizione fallisce.
RA.


5

2019:

React è un sacco di utility. Ma non è necessario alcun npmpacchetto per questo. basta creare da qualche parte la funzione classnamese chiamarla quando serve;

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

o

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

esempio

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

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

Solo per ispirazione

dichiara l'elemento helper e lo usa come togglemetodo

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

esempio:

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

function classstate(obj){
  for( let n in obj) classes.toggle(n,obj[n]);
 return classes; 
}

4

Soluzione più elegante, che è meglio per manutenzione e leggibilità:

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

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

<Element className={classNames.join(' ')}/>

3

puoi usare questo:

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

2

Questo funzionerebbe per te

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

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

return (
            ...
            <div className={_myClasses}>
               ...
            </div>
    );
  }
});

1

Puoi usare questo pacchetto npm. Gestisce tutto e ha opzioni per classi statiche e dinamiche basate su una variabile o una funzione.

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

In base al valore di this.props.showBulkActionste puoi cambiare classe in modo dinamico come segue.

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

1

Vorrei aggiungere che puoi anche usare un contenuto variabile come parte della classe

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

Il contesto è una chat tra un bot e un utente e gli stili cambiano a seconda del mittente, questo è il risultato del browser:

<img src="http://imageurl" alt="Avatar" class="img-bot">

1

Questo è utile quando hai più di una classe da aggiungere. È possibile unire tutte le classi nella matrice con uno spazio.

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

1

Sostituire:

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

con:

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


0

Ho trovato questo che spiega come farlo con un ternario e con la libreria Classnames

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.