Come aggiungere più classi a un componente ReactJS


348

Sono nuovo di ReactJS e JSX e sto riscontrando un piccolo problema con il codice seguente.

Sto cercando di aggiungere più classi classNameall'attributo su ciascuna li:

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

Il mio componente React è:

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

Ho trovato una risposta breif qui stackoverflow.com/a/36209517/4125588 , basta usare JavaScript per aderire a queste classi, statiche o dinamiche, con l'operatore '+', ricordarsi di inserire '' prima delle classi tranne la prima, come reale la classe in HTML dovrebbe essere come 'ab c', anche spazio tra di loro.
Fadeoc Khaos,


1
Perché non classNames={{foo: true, bar: true, baz: false}}e classNames={["foo", "bar"]}solo il lavoro ?
Peter V. Mørch,

Risposte:


221

Uso i nomi di classe quando è necessaria una discreta quantità di logica per decidere (non) utilizzare le classi. Un esempio troppo semplice :

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

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

Detto questo, se non si desidera includere una dipendenza, ci sono risposte migliori di seguito.


190
È un
peccato che

4
@ user959690 Questo è un esempio. Questa libreria è molto utile quando fai queste cose molto e hai una logica complessa su quando le classi devono essere applicate o meno. Se stai facendo qualcosa di semplice, assicurati di utilizzare solo i modelli, ma ogni caso è diverso e il lettore dovrebbe scegliere lo strumento giusto per il loro lavoro.
Jack,

7
@ user959690 Vale la pena notare che ora è installato da NPM quando si utilizza Webpack , import classNames from 'classnames'quindi da utilizzare in un componente className={classNames(classes.myFirstClass, classes.mySecondClass)} .
Hooligancat,

5
Non è necessario utilizzare una libreria esterna, vedere la mia risposta di seguito.
Huw Davies,

1
La biblioteca ha altri vantaggi: 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

396

Uso ES6 letterali template . Per esempio:

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

E poi basta renderlo:

<input className={classes} />

Versione a una fodera:

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

158
Inoltre:<input className={`class1 ${class2}`}>
Cody Moniz,

3
@unyo Per favore pubblica il tuo commento come risposta per poterlo votare. Lo merita così tanto. Ho cercato 1 ora per qualcosa di semplice come questo, e ora lo trovo sepolto come un commento. Grazie.
Souvik Ghosh,

Ciò si traduce in <input class=" form-control input-lg round-lg" />. Nota lo spazio extra all'inizio. Questo è valido, ma brutto. Persino reagire alle FAQ consiglia un altro modo o usare il pacchetto classnames: reazionejs.org/docs/faq-styling.html
Nakedible

Non riesco a capire perché avresti importato una libreria (come nella risposta accettata) per impostare solo alcune classi che possono essere impostate utilizzando JavaScript Vanilla, che è comunque una soluzione più efficiente, più pulita e leggibile.
Marcus Parsons,

2
Questa è la risposta corretta L'uso di una dipendenza per questo, come suggerito nella risposta "corretta", è eccessivo.
TheDarkIn1978

171

Usa JavaScript.

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

Se si desidera aggiungere chiavi e valori basati su classi in un oggetto, è possibile utilizzare quanto segue:

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

O ancora più semplice:

const isEnabled = true;
const isChecked = false;

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

Ecco la linea che ha funzionato per me:className={['terra-Table', medOrder.resource.status]}
Doug Wilhelm,

1
@DougWilhelm Non penso che funzioni. Chiama implicitamente toString e crea un elenco di classi separato da virgole. github.com/facebook/react/issues/3138
0xcaff

6
Buona idea da usare className={[listOfClasses].join(' ')}funziona per me grazie!
Ala Eddine JEBALI

98

concat

Non c'è bisogno di essere fantasiosi, sto usando i moduli CSS ed è facile

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

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

Ciò comporterà:

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

In altre parole, entrambi gli stili

Condizionali

Sarebbe facile usare la stessa idea con if's

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

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

1
Questo ha funzionato per me, insieme ai nomi '-', ovvero: <nav className = {styles.navbar + "" + styles ['navbar-default']}>
Flinkman

LOL, spacco la testa e la risposta è semplice: D. A parte questo lavoro anche con CSS Loader Module
GusDeCooL

Il problema è che non puoi avere classi opzionali (se non definito, quindi non verrà aggiunto), quindi dipende che tu sia sicuro che la tua classe non sia nulla (non opzionale). In caso di facoltativo non c'è niente di meglio di un helper come classi (). possiamo usare un ternario con modelli come quel className={cursore $ {className? `$ {className} : ''}}` `. Ma è molto. [nota: 'qualcosa' + undefined = 'qualcosa di sottofinito'. Js conversione dinamica.
Mohamed Allal,

Certo che puoi, basta dichiarare una variabile sopra e usarla in modo condizionale :)
Jamie Hutber

42

Ciò può essere ottenuto con i template letterali ES6:

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

1
questo ha funzionato quasi per me, dovevo solo interpolare anche la classe1 e niente più errori, quindi sembra così <input className={`${class1} ${class2}`}>
Kingston Fortune,

35

Puoi creare un elemento con più nomi di classe come questo:

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

Naturalmente, puoi usare una stringa contenente i nomi delle classi e manipolare questa stringa per aggiornare i nomi delle classi dell'elemento.

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

1
Hai provato questo? L'ho fatto :)
corvo

Si l'ho fatto. In realtà, lo sto usando abbastanza spesso ma ho appena visto e corretto un refuso. Naturalmente la stringa contenente i nomi delle classi nella prima riga deve essere creata usando "invece di '. Mi dispiace per quello.
nightlyop,

20

Ecco come puoi farlo con ES6:

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

Puoi elencare più classi e condizioni e puoi anche includere classi statiche. Non è necessario aggiungere una libreria aggiuntiva.

In bocca al lupo ;)


2
Ciò si traduce in HTML molto brutto, considerando tutto lo spazio bianco extra.
Nakedible,

2
Non è necessario scrivere così. Questo è solo un esempio che spiega meglio la soluzione. E sempre in produzione hai la versione ridotta :)
Hristo Eftimov,

18

Vanilla JS

Non sono necessarie librerie esterne: basta usare le stringhe di modello ES6 :

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

Vanilla JS NON è ES6. Ma mi piace il tuo esempio.
RyanNerd,

8
@RyanNerd Intendi "ES6 non è vaniglia JS"? Ad ogni modo, lo è, perché vanilla js significa javascript senza alcun framework. ES6 è una versione più recente di javascript. - stackoverflow.com/a/20435685/5111113
Huw Davies il

Non è una risposta sbagliata ma potrebbe essere migliorata molto. Ad esempio, tutti gli altri hanno aggiunto esempi sugli stati.
JGallardo,

10

Forse i nomi delle classi possono aiutarti.

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

1
Puoi rendere questo esempio più utilizzabile.
JGallardo,

9

Non penso che dobbiamo usare un pacchetto esterno per aggiungere solo più classi.

Io personalmente uso

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

o

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

il secondo nel caso in cui sia necessario aggiungere o rimuovere le classi in modo condizionale.


1
questo aggiungerà solo una classe in entrambi i modi.
TrickOrTreat

6

Solo aggiungendo, possiamo filtrare le stringhe vuote.

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

6

Puoi creare un elemento con più nomi di classe come questo, ci ho provato in entrambi i modi, funziona benissimo ...

Se si importa un CSS, è possibile seguire questa procedura: Modo 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>
    );
  }
}

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

**

Se si applica CSS come interno:

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

Puoi fare quanto segue:

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

Una soluzione breve e semplice, spero che questo aiuti.



4

In ritardo alla festa, ma perché usare terze parti per un problema così semplice?

Puoi farlo come menzionato da @Huw Davies - il modo migliore

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

Entrambi sono buoni. Ma la scrittura può diventare complessa per un'app di grandi dimensioni. Per renderlo ottimale, faccio le stesse cose sopra ma lo metto in una classe di aiuto

Usando la mia funzione di aiuto di seguito, mi consente di mantenere la logica separata per le modifiche future e mi dà anche diversi modi per aggiungere le classi

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

o

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

Questa è la mia funzione di aiuto di seguito. L'ho messo in un helper.js dove tengo tutti i miei metodi comuni. Essendo una funzione così semplice, ho evitato di usare terze parti per mantenere il controllo

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

3

È possibile utilizzare le matrici e quindi unirle usando lo spazio.

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

Ciò comporterà:

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

3

So che questa è una risposta tardiva, ma spero che questo possa aiutare qualcuno.

Considera che hai definito le seguenti classi in un file css ' primary ', ' font-i ', ' font-xl '

  • Il primo passo sarebbe importare il file CSS.
  • Poi

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

farebbe il trucco!

Per maggiori informazioni: https://www.youtube.com/watch?v=j5P9FHiBVNo&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=20


3

per l'aggiunta di più classi

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

2

Utilizzando l'esempio di TodoTextInput.js di 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} />
    )
  } 

la sostituzione dei nomi di classe con un semplice codice js alla vaniglia avrà questo aspetto:

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

Se non hai voglia di importare un altro modulo, questa funzione funziona come il classNamesmodulo.

function classNames(rules) {
    var classes = ''

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

    return classes
} 

Puoi usarlo in questo modo:

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

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

Perché usare le chiusure se puoi fare lo stesso con la mappa o riduci? function classNames(rules) { return Object.entries(rules) .reduce( (arr, [cls, flag]) => { if (flag) arr.push(cls); return arr }, [] ).join(" ") }
Евгений Савичев

1

Questo è ciò che faccio:

Componente:

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

Componente chiamante:

<Button className = 'hashButton free anotherClass' />

1

Sto usando React 16.6.3 e @Material UI 3.5.1 ed è in grado di usare array in className come className={[classes.tableCell, classes.capitalize]}

Quindi nel tuo esempio, il seguente sarebbe simile.

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

Questo è quello che stavo facendo (anche se senza MUI) e non funziona, applica solo la prima classe - nessun avvertimento o lamentela.
Juan Lanus,

1

Usa https://www.npmjs.com/package/classnames

import classNames da 'classnames';

  1. Può utilizzare più classi utilizzando le virgole separate:

    <li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>
  2. Può usare più classi usando le virgole separate con condizione:

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

Anche l'uso dell'array come oggetti di scena per classNames funzionerà, ma avverte ad es

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


0

Uso il pacchetto 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
})} />

Puoi aggiungere classi in qualsiasi formato (Array, Object, Argument). Tutti i valori di verità da matrici o Argomenti più chiavi in ​​oggetti ugualitrue unire insieme.

per esempio:

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

I bind classNamesnel modulo CSS importato nel componente.

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

classnamesdà la possibilità di dichiarare classNameun elemento React in modo dichiarativo.

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

Di solito lo uso così: (nel tuo caso)

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

Quando si tratta di JSX e (di solito) abbiamo un po 'di json ... di quello che si fa in loop ... componente . mappa , oltre ad alcuni condizionale per verificare se esiste la proprietà json per rendere il nome della classe in base al valore della proprietà da JSON. Nell'esempio seguente component_color e component_dark_shade sono proprietà di component.map ()

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

Output: <div class="component no-color light" .... Oppure: a <div class="component blue dark" ....seconda dei valori dalla mappa ...


0

Quando ho molte classi diverse, ho trovato utile quanto segue.

Il filtro rimuove qualsiasi nullvalore e il join inserisce tutti i valori rimanenti in una stringa separata da spazio.

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

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