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?


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.


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.


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

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

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



8

Falls Sie nur einen optionalen Klassennamen benötigen:

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

1
Dadurch wird die falseKlasse angehängt , wenn die Bedingung fehlschlägt.
RA.

3
Nein, das tut es nicht
madhu131313


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

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

3

Sie können dies verwenden:

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

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

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"

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

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

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

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


0

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.