So fügen Sie einer ReactJS-Komponente mehrere Klassen hinzu


345

Ich bin neu in ReactJS und JSX und habe ein kleines Problem mit dem folgenden Code.

Ich versuche, dem classNameAttribut jeweils mehrere Klassen hinzuzufügen li:

<li key={index} className={activeClass, data.class, "main-class"}></li>

Meine Reaktionskomponente ist:

var AccountMainMenu = React.createClass({
  getInitialState: function() {
    return { focused: 0 };
  },

  clicked: function(index) {
    this.setState({ focused: index });
  },

  render: function() {
    var self = this;
    var accountMenuData = [
      {
        name: "My Account",
        icon: "icon-account"
      },
      {
        name: "Messages",
        icon: "icon-message"
      },
      {
        name: "Settings",
        icon: "icon-settings"
      }
    /*{
        name:"Help &amp; Support &nbsp; <span class='font-awesome icon-support'></span>(888) 664.6261",
        listClass:"no-mobile last help-support last"
      }*/
    ];

    return (
      <div className="acc-header-wrapper clearfix">
        <ul className="acc-btns-container">
          {accountMenuData.map(function(data, index) {
            var activeClass = "";

            if (self.state.focused == index) {
              activeClass = "active";
            }

            return (
              <li
                key={index}
                className={activeClass}
                onClick={self.clicked.bind(self, index)}
              >
                <a href="#" className={data.icon}>
                  {data.name}
                </a>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
});

ReactDOM.render(<AccountMainMenu />, document.getElementById("app-container"));

Ich habe hier eine kurze Antwort gefunden. Stackoverflow.com/a/36209517/4125588 Verwenden Sie einfach JavaScript, um diese statischen oder dynamischen Klassen mit dem Operator '+' zu verbinden. Denken Sie daran, '' vor den Klassen außer der ersten als echte einzufügen Klasse in HTML sollte wie 'ab c' sein, auch Leerzeichen zwischen ihnen.
Fadeoc Khaos

Mögliches Duplikat der
Übergabe

1
Warum nicht classNames={{foo: true, bar: true, baz: false}}und classNames={["foo", "bar"]}einfach arbeiten ?
Peter V. Mørch

Antworten:


221

Ich verwende Klassennamen, wenn eine angemessene Menge an Logik erforderlich ist, um zu entscheiden, welche Klassen (nicht) verwendet werden sollen. Ein zu einfaches Beispiel :

...
    var liClasses = classNames({
      'main-class': true,
      'activeClass': self.state.focused === index
    });

    return (<li className={liClasses}>{data.name}</li>);
...

Wenn Sie jedoch keine Abhängigkeit einfügen möchten, finden Sie unten bessere Antworten.


187
Das ist schade, dass Sie eine Bibliothek mit Klassennamen einbringen mussten, um einem Element zwei Klassen hinzuzufügen :(
user959690

4
@ user959690 Dies ist ein Beispiel. Diese Bibliothek ist sehr schön, wenn Sie diese Dinge häufig tun und Sie haben eine komplexe Logik, wann Klassen angewendet werden müssen oder nicht. Wenn Sie etwas Einfaches tun, verwenden Sie sicher nur Vorlagen, aber jeder Fall ist anders und der Leser sollte das richtige Werkzeug für seine Arbeit auswählen.
Jack

7
@ user959690 Es ist erwähnenswert, dass es jetzt von NPM installiert wird, wenn Webpack verwendet wird , um es import classNames from 'classnames'dann in einer Komponente zu verwenden className={classNames(classes.myFirstClass, classes.mySecondClass)} .
Hooligancat

5
Sie müssen keine externe Bibliothek verwenden, siehe meine Antwort unten.
Huw Davies

1
Bibliothek hat andere Vorteile: var btnClass = classNames({ btn: true, 'btn-pressed': this.state.isPressed, 'btn-over': !this.state.isPressed && this.state.isHovered }); return <button className={btnClass}>{this.props.label}</button>;
AmitJS94

394

Ich verwende ES6 Vorlagenliterale . Zum Beispiel:

const error = this.state.valid ? '' : 'error'
const classes = `form-control round-lg ${error}`

Und dann einfach rendern:

<input className={classes} />

Einzeiler-Version:

<input className={`form-control round-lg ${this.state.valid ? '' : 'error'}`} />

157
Auch:<input className={`class1 ${class2}`}>
Cody Moniz

3
@unyo Bitte poste deinen Kommentar als Antwort, damit ich ihn positiv bewerten kann. Es hat es so sehr verdient. Ich habe 1 Stunde lang nach etwas so Einfachem gesucht, und jetzt finde ich dies als Kommentar vergraben. Vielen Dank.
Souvik Ghosh

Dies führt zu <input class=" form-control input-lg round-lg" />. Beachten Sie den zusätzlichen Platz am Anfang. Das ist gültig, aber hässlich. Sogar Reagieren FAQ empfiehlt eine andere Möglichkeit oder die Verwendung des Klassennamen-Pakets: reactjs.org/docs/faq-styling.html
Nakedible

Ich kann nicht verstehen, warum Sie eine Bibliothek importieren würden (wie in der akzeptierten Antwort), um nur einige Klassen festzulegen, die mit Vanilla JavaScript festgelegt werden können. Dies ist sowieso eine effizientere, sauberere und lesbarere Lösung.
Marcus Parsons

2
Dies ist die richtige Antwort. Die Verwendung einer Abhängigkeit hierfür, wie in der "richtigen" Antwort vorgeschlagen, ist übertrieben.
TheDarkIn1978

171

Verwenden Sie einfach JavaScript.

<li className={[activeClass, data.klass, "main-class"].join(' ')} />

Wenn Sie einem Objekt klassenbasierte Schlüssel und Werte hinzufügen möchten, können Sie Folgendes verwenden:

function classNames(classes) {
  return Object.entries(classes)
    .filter(([key, value]) => value)
    .map(([key, value]) => key)
    .join(' ');
}

const classes = {
  'maybeClass': true,
  'otherClass': true,
  'probablyNotClass': false,
};

const myClassNames = classNames(classes);
// Output: "maybeClass otherClass"

<li className={myClassNames} />

Oder noch einfacher:

const isEnabled = true;
const isChecked = false;

<li className={[isEnabled && 'enabled', isChecked && 'checked']
  .filter(e => !!e)
  .join(' ')
} />
// Output:
// <li className={'enabled'} />

Hier ist die Zeile, die für mich funktioniert hat:className={['terra-Table', medOrder.resource.status]}
Doug Wilhelm

1
@ DougWilhelm Ich denke nicht, dass das funktioniert. Es ruft implizit toString auf und erstellt eine durch Kommas getrennte Liste von Klassen. github.com/facebook/react/issues/3138
0xcaff

6
Gute Idee, className={[listOfClasses].join(' ')}es zu benutzen , funktioniert für mich, danke!
Ala Eddine JEBALI

97

Concat

Keine Notwendigkeit, ich verwende CSS-Module und es ist einfach

import style from '/css/style.css';

<div className={style.style1+ ' ' + style.style2} />

Dies führt zu:

<div class="src-client-css-pages-style1-selectionItem src-client-css-pages-style2">

Mit anderen Worten, beide Stile

Bedingungen

Es wäre einfach, die gleiche Idee mit if's zu verwenden

const class1 = doIHaveSomething ? style.style1 : 'backupClass';

<div className={class1 + ' ' + style.style2} />

1
Dies funktionierte für mich zusammen mit '-' Namen, dh: <nav className = {styles.navbar + "" + styles ['navbar-default']}>
Flinkman

LOL, ich knacke meinen Kopf und die Antwort ist einfach concat: D. Übrigens funktioniert dies auch mit dem CSS Loader Module
GusDeCooL

Das Problem dabei ist, dass Sie keine optionalen Klassen haben können (wenn diese nicht definiert sind, werden sie nicht hinzugefügt). Es hängt also davon ab, ob Sie sicher sind, dass Ihre Klasse nicht null ist (nicht optional). Im Falle von optional gibt es keinen besseren als einen Helfer wie classes (). Wir können ein Ternär mit Vorlagen wie diesem className={Schieberegler $ {className? `$ {className} : ''}}` `. Aber es ist viel. [Anmerkung: 'etwas' + undefiniert = 'etwas unterdefiniert'. Js dynamische Konvertierung.
Mohamed Allal

Sicher können Sie, deklarieren Sie einfach eine Variable oben und verwenden Sie sie bedingt :)
Jamie Hutber

42

Dies kann mit ES6-Vorlagenliteralen erreicht werden:

<input className={`class1 ${class2}`}>

1
Das hat fast für mich funktioniert. Ich musste nur die Klasse 1 interpolieren und keine Fehler mehr, also sieht es so aus <input className={`${class1} ${class2}`}>
Kingston Fortune

35

Sie können ein Element mit mehreren Klassennamen wie folgt erstellen:

<li className="class1 class2 class3">foo</li>

Natürlich können Sie eine Zeichenfolge verwenden, die die Klassennamen enthält, und diese Zeichenfolge bearbeiten, um die Klassennamen des Elements zu aktualisieren.

var myClassNammes = 'class1 class2 class3';
...
<li className={myClassNames}>foo</li>

1
Hast du das getestet? Ich habe :)
Rabe

Ja, habe ich. Eigentlich benutze ich es ziemlich oft, habe aber nur einen Tippfehler gesehen und korrigiert. Natürlich muss die Zeichenfolge, die die Klassennamen in der ersten Zeile enthält, "anstelle von verwendet werden '. Das tut mir leid.
Nightlyop

20

So können Sie das mit ES6 machen:

className = {`
      text-right
      ${itemId === activeItemId ? 'active' : ''}
      ${anotherProperty === true ? 'class1' : 'class2'}
`}

Sie können mehrere Klassen und Bedingungen auflisten und auch statische Klassen einschließen. Es ist nicht erforderlich, eine zusätzliche Bibliothek hinzuzufügen.

Viel Glück ;)


2
Dies führt zu sehr hässlichem HTML, wenn man alle zusätzlichen Leerzeichen berücksichtigt.
Nakedible

2
Es ist nicht notwendig, so zu schreiben. Dies ist nur ein Beispiel, das die Lösung besser erklärt. Und immer in Produktion haben Sie die minimierte Version :)
Hristo Eftimov

18

Vanilla JS

Keine Notwendigkeit für externe Bibliotheken - verwenden Sie einfach ES6- Vorlagenzeichenfolgen :

<i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>

Vanilla JS ist NICHT ES6. Aber ich mag dein Beispiel.
RyanNerd

8
@ RyanNerd Meinst du "ES6 ist nicht Vanille JS"? Wie auch immer, weil Vanille js Javascript ohne Frameworks bedeutet. ES6 ist eine neuere Version von Javascript. - stackoverflow.com/a/20435685/5111113
Huw Davies

Keine falsche Antwort, könnte aber stark verbessert werden. Zum Beispiel haben alle anderen Beispiele zu Zuständen hinzugefügt.
JGallardo

10

Vielleicht können Klassennamen Ihnen helfen.

var classNames = require('classnames');
classNames('foo', {'xx-test': true, bar: false}, {'ox-test': false}); // => 'foo xx-test'

1
Können Sie dieses Beispiel benutzerfreundlicher machen?
JGallardo

9

Ich denke nicht, dass wir ein externes Paket verwenden müssen, um nur mehrere Klassen hinzuzufügen.

Ich persönlich benutze

<li className={`li active`}>Stacy</li>

oder

<li className={`li ${this.state.isActive ? 'active' : ''}`}>Stacy<li>

die zweite für den Fall, dass Sie Klassen bedingt hinzufügen oder entfernen müssen.


1
Dadurch wird nur eine Klasse hinzugefügt.
TrickOrTreat

6

Durch einfaches Hinzufügen können wir leere Zeichenfolgen herausfiltern.

className={[
    'read-more-box',
    this.props.className,
    this.state.isExpanded ? 'open' : 'close',
].filter(x => !!x).join(' ')}

6

Sie können ein Element mit mehreren Klassennamen wie diesem erstellen. Ich habe es in beide Richtungen versucht. Es funktioniert einwandfrei ...

Wenn Sie CSS importieren, können Sie folgendermaßen vorgehen: Weg 1:

import React, { Component, PropTypes } from 'react';
import csjs from 'csjs';
import styles from './styles';
import insertCss from 'insert-css';
import classNames from 'classnames';
insertCss(csjs.getCss(styles));
export default class Foo extends Component {
  render() {
    return (
      <div className={[styles.class1, styles.class2].join(' ')}>
        { 'text' }
      </div>
    );
  }
}

Weg 2:

import React, { Component, PropTypes } from 'react';
import csjs from 'csjs';
import styles from './styles';
import insertCss from 'insert-css';
import classNames from 'classnames';
insertCss(csjs.getCss(styles));
export default class Foo extends Component {
  render() {
    return (
      <div className={styles.class1 + ' ' + styles.class2}>
        { 'text' }
      </div>
    );
  }
}

** **.

Wenn Sie CSS als intern anwenden:

const myStyle = {
  color: "#fff"
};

// React Element using Jsx
const myReactElement = (
  <h1 style={myStyle} className="myClassName myClassName1">
    Hello World!
  </h1>
);

ReactDOM.render(myReactElement, document.getElementById("app"));
.myClassName {
  background-color: #333;
  padding: 10px;
}
.myClassName1{
  border: 2px solid #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.production.min.js"></script>
<div id="app">
  
</div>


6

Sie können Folgendes tun:

<li key={index} className={`${activeClass} ${data.class} main-class`}></li>

Eine kurze und einfache Lösung, hoffe das hilft.



4

Spät zur Party, aber warum sollte man einen Dritten für ein so einfaches Problem einsetzen?

Sie können es entweder tun, wie @Huw Davies erwähnt hat - der beste Weg

1. <i className={`${styles['foo-bar-baz']} fa fa-user fa-2x`}/>
2. <i className={[styles['foo-bar-baz'], 'fa fa-user', 'fa-2x'].join(' ')}

Beide sind gut. Für eine große App kann das Schreiben jedoch komplex werden. Um es optimal zu machen, mache ich das Gleiche wie oben, aber stelle es in eine Hilfsklasse

Wenn ich meine unten stehende Hilfsfunktion verwende, kann ich die Logik für zukünftige Bearbeitungen getrennt halten und habe mehrere Möglichkeiten, die Klassen hinzuzufügen

classNames(styles['foo-bar-baz], 'fa fa-user', 'fa-2x')

oder

classNames([styles['foo-bar-baz], 'fa fa-user', 'fa-2x'])

Dies ist meine Hilfsfunktion unten. Ich habe es in eine helper.js gestellt, in der ich alle meine gängigen Methoden behalte. Da es sich um eine so einfache Funktion handelt, habe ich es vermieden, Dritte zu verwenden, um die Kontrolle zu behalten

export function classNames (classes) {
    if(classes && classes.constructor === Array) {
        return classes.join(' ')
    } else if(arguments[0] !== undefined) {
        return [...arguments].join(' ')
    }
    return ''
}

3

Sie können Arrays verwenden und sie dann mit Leerzeichen verbinden.

<li key={index} className={[activeClass, data.class, "main-class"].join(' ')}></li>

Dies führt zu:

<li key={index} class="activeClass data.class main-class"></li>

3

Ich weiß, dass dies eine späte Antwort ist, aber ich hoffe, dass dies jemandem hilft.

Beachten Sie, dass Sie die folgenden Klassen in einer CSS-Datei ' primary ', ' font-i ', ' font-xl ' definiert haben.

  • Der erste Schritt wäre das Importieren der CSS-Datei.
  • Dann

<h3 class = {` ${'primary'} ${'font-i'} font-xl`}> HELLO WORLD </h3>

würde den Trick machen!

Für weitere Informationen: https://www.youtube.com/watch?v=j5P9FHiBVNo&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=20


3

für weitere Klassen hinzufügen

... className={`${classes.hello} ${classes.hello1}`...

2

Verwenden Sie das Beispiel TodoTextInput.js von Facebook

render() {
    return (
      <input className={
        classnames({
          edit: this.props.editing,
          'new-todo': this.props.newTodo
        })}
        type="text"
        placeholder={this.props.placeholder}
        autoFocus="true"
        value={this.state.text}
        onBlur={this.handleBlur}
        onChange={this.handleChange}
        onKeyDown={this.handleSubmit} />
    )
  } 

Das Ersetzen von Klassennamen durch einfachen Vanille-JS-Code sieht folgendermaßen aus:

render() {
    return (
      <input
        className={`
          ${this.props.editing ? 'edit' : ''} ${this.props.newTodo ? 'new-todo' : ''}
        `}
        type="text"
        placeholder={this.props.placeholder}
        autoFocus="true"
        value={this.state.text}
        onBlur={this.handleBlur}
        onChange={this.handleChange}
        onKeyDown={this.handleSubmit} />
    )
  }

2

Wenn Sie kein anderes Modul importieren möchten, funktioniert diese Funktion wie das classNamesModul.

function classNames(rules) {
    var classes = ''

    Object.keys(rules).forEach(item => {    
        if (rules[item])
            classes += (classes.length ? ' ' : '') + item
    })

    return classes
} 

Sie können es so verwenden:

render() {
    var classes = classNames({
        'storeInfoDiv': true,  
        'hover': this.state.isHovered == this.props.store.store_id
    })   

    return (
        <SomeComponent style={classes} />
    )
}

Warum Verschlüsse verwenden, wenn Sie dasselbe mit der Karte tun oder reduzieren können? function classNames(rules) { return Object.entries(rules) .reduce( (arr, [cls, flag]) => { if (flag) arr.push(cls); return arr }, [] ).join(" ") }
26вгений Савичев

1

Das ist, was ich tue:

Komponente:

const Button = ({ className }) => (
  <div className={ className }> </div>
);

Komponente aufrufen:

<Button className = 'hashButton free anotherClass' />

1

Ich verwende React 16.6.3 und @Material UI 3.5.1 und kann Arrays in className wie verwenden className={[classes.tableCell, classes.capitalize]}

In Ihrem Beispiel wäre das Folgende ähnlich.

<li key={index} className={[activeClass, data.class, "main-class"]}></li>

Dies ist, was ich getan habe (wenn auch kein MUI) und funktioniert nicht, gilt nur für die erste Klasse - keine Warnung oder Beschwerde.
Juan Lanus

1

Verwenden Sie https://www.npmjs.com/package/classnames

importiere Klassennamen aus 'Klassennamen';

  1. Kann mehrere Klassen mit getrennten Komas verwenden:

    <li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>
  2. Kann mehrere Klassen mit durch Bedingung getrennten Komas verwenden:

    <li className={classNames(classes.buttonArea, !nodes.length && classes.buttonAreaHidden)}>Hello World</li> 

Die Verwendung eines Arrays als Requisiten für classNames funktioniert ebenfalls, gibt jedoch eine Warnung aus, z

className={[classes.tableCellLabel, classes.tableCell]}


0

Ich benutze das Paket rc-classnames .

// ES6
import c from 'rc-classnames';

// CommonJS
var c = require('rc-classnames');

<button className={c('button', {
  'button--disabled': isDisabled,
  'button--no-radius': !hasRadius
})} />

Sie können Klassen in jedem Format (Array, Objekt, Argument) hinzufügen. Alle wahrheitsgemäßen Werte aus Arrays oder Argumenten sowie Schlüssel in Objekten, die gleich sindtrue um zusammengeführt zu werden.

zum Beispiel:

ReactClassNames('a', 'b', 'c') // => "a b c"
ReactClassNames({ 'a': true, 'b': false, c: 'true' }) // => "a c"
ReactClassNames(undefined, null, 'a', 0, 'b') // => "a b"

0

Ich bind classNameszum CSS-Modul in die Komponente importiert.

import classNames from 'classnames'; 
import * as styles from './[STYLES PATH];
const cx = classNames.bind(styles); 

classnamesgibt die Möglichkeit, deklarativ classNamefür ein React-Element zu deklarieren .

Ex:

<div classNames={cx(styles.titleText)}> Lorem </div>

<div classNames={cx('float-left')}> Lorem </div> // global css declared without css modules
<div classNames={cx( (test === 0) ?
             styles.titleText : 
             styles.subTitleText)}>  Lorem </div> // conditionally assign classes

<div classNames={cx(styles.titleText, 'float-left')}> Lorem </div> //combine multiple classes

0

Ich benutze es normalerweise so: (in deinem Fall)

    <li  key={index} className={
        "component " +
        `${activeClass? activeClass: " not-an-active-class "}` +
        `${data.class? " " + data.class : " no-data-class "}`
   } />

Wenn es um JSX geht und (normalerweise) haben wir etwas json ... als Sie es schleifen ... Komponente . map sowie einige Bedingungen, um zu überprüfen, ob die json-Eigenschaft vorhanden ist, um den Klassennamen abhängig vom Eigenschaftswert von JSON zu rendern. Im folgenden Beispiel sind component_color und component_dark_shade Eigenschaften von component.map ()

   <div className={
        "component " +
        `${component_color? component_color: " no-color "}` +
        `${component_dark_shade? " " + component_dark_shade : " light "}`
   }/>

Ausgabe: <div class="component no-color light" .... Oder: <div class="component blue dark" ....abhängig von den Werten aus der Karte ...


0

Wenn ich viele verschiedene Klassen habe, habe ich Folgendes als nützlich empfunden.

Der Filter entfernt alle nullWerte und der Join fügt alle verbleibenden Werte in eine durch Leerzeichen getrennte Zeichenfolge ein.

const buttonClasses = [
    "Button", 
    disabled ? "disabled" : null,
    active ? "active" : null
].filter((class) => class).join(" ")

<button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}>
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.