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"));
Tyrannisieren
quelle
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.

Jack
quelle
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'}`} />
Damjan Pavlica
quelle
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'} />
0xcaff
quelle
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} />
Jamie Hutber
quelle
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}`}>
Cody Moniz
quelle
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>
Nightlyop
quelle
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 ;)

Hristo Eftimov
quelle
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`}/>
Huw Davies
quelle
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'
xsong
quelle
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.

Pasham Akhil Kumar Reddy
quelle
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(' ')}
Himanshu Jariyal
quelle
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>

Arvinda Kumar
quelle
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.

Alberto Perez
quelle
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 ''
}
Elton Jain
quelle
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>
Vinay Jariya
quelle
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

Achintha Isuru
quelle
3

für weitere Klassen hinzufügen

... className={`${classes.hello} ${classes.hello1}`...
Rama Krishna
quelle
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} />
    )
  }
Vlad Bezden
quelle
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} />
    )
}
Seth
quelle
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' />
RegarBoy
quelle
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>
Devakhim
quelle
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]}
Vikramjit Singh
quelle
Duplikat einer anderen vorhandenen Antwort .
Jack Bashford
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"
Morajabi
quelle
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
Rajendra Kumar Vankadari
quelle
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 ...

StefaDesign
quelle
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}>
Michael Murphy
quelle