Reagiere Js unter bedingter Anwendung von Klassenattributen

333

Ich möchte diese Schaltflächengruppe bedingt ein- und ausblenden, je nachdem, was von der übergeordneten Komponente übergeben wird, die folgendermaßen aussieht:

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

Mit den {this.props.showBulkActions? 'Verborgenes zeigen'}. Mache ich hier etwas falsch?

Apexdodge
quelle
Möglicherweise möchten Sie auch React-Bootstrap in Betracht ziehen , da hierdurch einige der Klassenelemente in Komponenteneigenschaften abstrahiert werden, wodurch das, was Sie versuchen, etwas einfacher wird.
Dancrumb

Antworten:

587

Die geschweiften Klammern befinden sich innerhalb der Zeichenfolge, daher wird sie als Zeichenfolge ausgewertet. Sie müssen draußen sein, also sollte dies funktionieren:

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

Beachten Sie das Leerzeichen nach "Nach rechts ziehen". Sie möchten nicht versehentlich die Klasse "pull-rightshow" anstelle von "pull-right show" bereitstellen. Auch die Klammern müssen vorhanden sein.

spitfire109
quelle
3
Vielen Dank! Ich musste es leicht modifizieren, weil es aus irgendeinem Grund überhaupt nicht btn-group pull-right ausgab. Einfach zeigen oder verstecken.
Apexdodge
Dies ist besonders hilfreich in bestimmten Fällen, in denen dies classnamesmöglicherweise nicht angemessen ist. Wenn Sie in Ihrer renderFunktion sind und eine haben map, wissen Sie möglicherweise nur, ob Sie eine Klasse zum Zeitpunkt des Renderns hinzufügen möchten. Diese Antwort ist daher sehr nützlich.
Dave Cooper
Eine großartige Alternative, anstatt eine Reihe von bedingten Vorlagen in Ihrem Rendering oder Return zu haben
Devonj
@apexdodge welche Modifikation du machen musstest. Ich habe das gleiche Problem.
RamY
1
@RamY Eine Möglichkeit besteht darin, alle Klassen in die Bedingung zu setzen this.props.showBulkActions ? 'btn-group pull-right show' : 'btn-group pull-right hidden'). Nicht elegant, aber es funktioniert.
Ian
87

Wie andere kommentiert haben, ist das Dienstprogramm classnames der derzeit empfohlene Ansatz, um bedingte CSS-Klassennamen in ReactJs zu verarbeiten.

In Ihrem Fall sieht die Lösung folgendermaßen aus:

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

...

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

Als Randnotiz würde ich Ihnen empfehlen, die Verwendung von beiden showund hiddenKlassen zu vermeiden , damit der Code einfacher ist. Höchstwahrscheinlich müssen Sie keine Klasse festlegen, damit etwas standardmäßig angezeigt wird.

Diego V.
quelle
11
Könnten Sie näher erläutern, dass das Dienstprogramm classNames der "derzeit empfohlene Ansatz" ist? Wird das irgendwo in einem angesehenen Best-Practice-Dokument festgehalten? Oder einfach eine Art Mundpropaganda um React und classNamesim Moment?
Alexander Nied
6
@anied Zum Zeitpunkt des Schreibens wurde es in der offiziellen React-Dokumentation empfohlen: web.archive.org/web/20160602124910/http://facebook.github.io:80/…
Diego V
3
In der neuesten Dokumentation wird immer noch erwähnt : " Wenn Sie häufig Code wie diesen schreiben, kann das Klassennamenpaket dies vereinfachen. "
Franklin Yu
66

Wenn Sie einen Transpiler (wie Babel oder Traceur) verwenden, können Sie die neuen ES6 " Template Strings " verwenden.

Hier ist die Antwort von @ spitfire109, entsprechend geändert:

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

Mit diesem Ansatz können Sie solche netten Dinge tun, indem Sie entweder s-is-shownoder Folgendes rendern s-is-hidden:

<div className={`s-${this.props.showBulkActions ? 'is-shown' : 'is-hidden'}`}>
Bertrand
quelle
20
Seien Sie vorsichtig mit dem zweiten Ansatz, insbesondere in großen Codebasen, da dadurch die Klassenzeichenfolgen weniger greifbar werden. Wenn beispielsweise jemand nach s-is-shownoder s-is-hiddenin der Codebasis sucht , findet er diesen Code nicht.
Markieren Sie den
15

Sie können hier String-Literale verwenden

const Angle = ({show}) => {

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

   return <i className={angle} />
}
Musa
quelle
9

Wenn man sich die gute Antwort von @ spitfire109 ansieht, könnte man so etwas tun:

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

  return names.join(' ');
}

und dann innerhalb der Renderfunktion:

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

hält das jsx kurz

flockig
quelle
8

Oder verwenden Sie npm- Klassennamen . Es ist sehr einfach und nützlich, insbesondere zum Erstellen der Klassenliste

Bleistiftcheck
quelle
8

Falls Sie nur einen optionalen Klassennamen benötigen:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? "show" : "")}>
Eugene Chybisov
quelle
1
Dadurch wird die falseKlasse angehängt , wenn die Bedingung fehlschlägt.
RA.
3
Nein, das tut es nicht
madhu131313
6

Sie können ES6-Arrays anstelle von Klassennamen verwenden. Die Antwort basiert auf dem Artikel von Dr. Axel Rauschmayer: Bedingtes Hinzufügen von Einträgen in Array- und Objektliteralen .

<div className={[
                 "classAlwaysPresent", 
                 ...Array.from(condition && ["classIfTrue"])
                ].join(" ")} />
Tudor Morar
quelle
Bitte erweitern Sie dies, was ist Zustand?
Mibbit
const condition = (1 === 1);
Tudor Morar
5

2019:

Reagieren ist See viele Dienstprogramme. Dafür brauchen Sie aber kein npmPaket. Erstellen Sie einfach irgendwo die Funktion classnamesund rufen Sie sie bei Bedarf auf.

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

oder

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

Beispiel

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

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

Nur zur Inspiration

Deklarieren Sie das Hilfselement und verwenden Sie es als toggleMethode

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

Beispiel:

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

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

Elegantere Lösung, die für Wartung und Lesbarkeit besser ist:

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

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

<Element className={classNames.join(' ')}/>
Nate Ben
quelle
3

Sie können dies verwenden:

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

Das würde für dich funktionieren

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

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

return (
            ...
            <div className={_myClasses}>
               ...
            </div>
    );
  }
});
Manoj Amalraj
quelle
1

Sie können dieses npm-Paket verwenden. Es behandelt alles und verfügt über Optionen für statische und dynamische Klassen, die auf einer Variablen oder einer Funktion basieren.

// 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"
Tushar Sharma
quelle
1

Basierend auf dem Wert von können this.props.showBulkActionsSie Klassen wie folgt dynamisch wechseln.

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

Ich möchte hinzufügen, dass Sie auch einen variablen Inhalt als Teil der Klasse verwenden können

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

Der Kontext ist ein Chat zwischen einem Bot und einem Benutzer, und die Stile ändern sich je nach Absender. Dies ist das Ergebnis des Browsers:

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

Dies ist nützlich, wenn Sie mehr als eine Klasse anhängen müssen. Sie können alle Klassen in einem Array mit einem Leerzeichen verbinden.

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

Ersetzen:

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

mit:

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

Verweis auf @split fire answer, wir können es mit Vorlagenliteralen aktualisieren, die besser lesbar sind. Als Referenz Checkout Javascript-Vorlagenliteral

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

Ich fand dies , das erklärt, wie man es mit einem ternären und mit Classnames Library macht

Chachan
quelle