Comment ajouter plusieurs classes à un composant ReactJS


346

Je suis nouveau sur ReactJS et JSX et j'ai un petit problème avec le code ci-dessous.

J'essaie d'ajouter plusieurs classes à l' classNameattribut sur chacune li:

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

Mon composant React est:

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

J'ai trouvé une réponse brève ici stackoverflow.com/a/36209517/4125588 , il suffit d'utiliser JavaScript pour rejoindre ces classes, statiques ou dynamiques, avec l'opérateur '+', n'oubliez pas d'insérer '' avant les classes sauf la première, comme le vrai La classe en HTML devrait être comme «ab c», également un espace entre eux.
Fadeoc Khaos


1
Pourquoi ne pas travaillerclassNames={{foo: true, bar: true, baz: false}} et classNames={["foo", "bar"]}simplement ?
Peter V. Mørch

Réponses:


221

J'utilise des noms de classe quand il y a une bonne quantité de logique requise pour décider des classes à (ne pas) utiliser. Un exemple trop simple :

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

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

Cela dit, si vous ne voulez pas inclure de dépendance, il y a de meilleures réponses ci-dessous.


189
C'est dommage que vous ayez dû apporter une bibliothèque de noms de classes juste pour ajouter deux classes à un élément :(
user959690

4
@ user959690 Ceci est un exemple. Cette bibliothèque est très agréable lorsque vous faites beaucoup de choses et que vous avez une logique complexe sur le moment où les classes doivent être appliquées ou non. Si vous faites quelque chose de simple, utilisez simplement des modèles, mais chaque cas est différent et le lecteur doit choisir le bon outil pour son travail.
Jack

7
@ user959690 Il convient de noter qu'il est désormais installé par NPM lors de l'utilisation de Webpack , donc import classNames from 'classnames'à utiliser dans un composant className={classNames(classes.myFirstClass, classes.mySecondClass)} .
Hooligancat

5
Pas besoin d'utiliser une bibliothèque externe, voir ma réponse ci-dessous.
Huw Davies

1
La bibliothèque a d'autres avantages: 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

395

J'utilise des ES6 modèles de littéraux . Par exemple:

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

Et puis il suffit de le rendre:

<input className={classes} />

Version à une ligne:

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

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

3
@unyo Veuillez poster votre commentaire comme réponse afin que je puisse le voter. Il le mérite tellement. Je cherche depuis 1 heure quelque chose d'aussi simple que cela, et maintenant je trouve cela enterré en tant que commentaire. Je vous remercie.
Souvik Ghosh

Cela se traduit par <input class=" form-control input-lg round-lg" />. Notez l'espace supplémentaire au début. C'est valide, mais moche. Même React FAQ recommande une autre méthode ou l'utilisation du package classnames
Nakedible

Je ne comprends pas pourquoi vous importeriez une bibliothèque (comme dans la réponse acceptée) pour simplement définir certaines classes qui peuvent être définies à l'aide de Vanilla JavaScript, qui est de toute façon une solution plus efficace, plus propre et plus lisible.
Marcus Parsons

2
Ceci est la bonne réponse. Utiliser une dépendance pour cela comme suggéré dans la réponse "correcte" est exagéré.
TheDarkIn1978

171

Utilisez simplement JavaScript.

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

Si vous souhaitez ajouter des clés et des valeurs basées sur des classes dans un objet, vous pouvez utiliser les éléments suivants:

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

Ou encore plus simple:

const isEnabled = true;
const isChecked = false;

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

Voici la ligne qui a fonctionné pour moi:className={['terra-Table', medOrder.resource.status]}
Doug Wilhelm

1
@DougWilhelm Je ne pense pas que cela fonctionne. Il appelle implicitement toString et crée une liste de classes séparées par des virgules. github.com/facebook/react/issues/3138
0xcaff

6
Bonne idée d'utiliser className={[listOfClasses].join(' ')}ça marche pour moi merci!
Ala Eddine JEBALI

98

Concat

Pas besoin d'être chic j'utilise des modules CSS et c'est facile

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

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

Cela se traduira par:

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

En d'autres termes, les deux styles

Conditionnels

Il serait facile d'utiliser la même idée avec if

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

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

1
Cela a fonctionné pour moi, avec les noms '-', c'est-à-dire: <nav className = {styles.navbar + "" + styles ['navbar-default']}>>
Flinkman

LOL, je me casse la tête et la réponse est simple: D. Btw ce travail aussi avec CSS Loader Module
GusDeCooL

Le problème avec cela est que vous ne pouvez pas avoir de classes optionnelles (si elles ne sont pas définies, elles ne seront pas ajoutées), cela dépend donc de la certitude que votre classe n'est pas nulle (non optionnelle). En cas de facultatif, il n'y a pas mieux qu'un assistant comme classes (). nous pouvons utiliser un ternaire avec des modèles comme ce className={curseur $ {className? `$ {className} : ''}}` `. Mais c'est beaucoup. [note: 'quelque chose' + undefined = 'quelque chose de sous-défini'. Conversion dynamique Js.
Mohamed Allal

Bien sûr, vous pouvez simplement déclarer une variable ci-dessus et l'utiliser conditionnellement :)
Jamie Hutber

42

Cela peut être réalisé avec les littéraux de modèle ES6:

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

1
cela a presque fonctionné pour moi J'ai juste eu à interpoler la classe 1 aussi et plus d'erreurs, donc ça ressemble à ça <input className={`${class1} ${class2}`}>
Kingston Fortune

35

Vous pouvez créer un élément avec plusieurs noms de classe comme celui-ci:

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

Naturellement, vous pouvez utiliser une chaîne contenant les noms de classe et manipuler cette chaîne pour mettre à jour les noms de classe de l'élément.

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

1
Avez-vous testé cela? Je l'ai fait :)
corbeau

Oui je l'ai fait. En fait, je l'utilise assez souvent, mais je viens de voir et de corriger une faute de frappe. Bien sûr, la chaîne contenant les noms de classe dans la première ligne doit être créée à la "place de '. Désolé pour ça.
soir

20

Voici comment vous pouvez le faire avec ES6:

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

Vous pouvez répertorier plusieurs classes et conditions et vous pouvez également inclure des classes statiques. Il n'est pas nécessaire d'ajouter une bibliothèque supplémentaire.

Bonne chance ;)


2
Cela se traduit par un code HTML très laid, compte tenu de tous les espaces supplémentaires.
Nakedible

2
Il n'est pas nécessaire d'écrire comme ça. Ceci est juste un exemple qui explique mieux la solution. Et toujours en production vous avez la version minifiée :)
Hristo Eftimov

18

Vanilla JS

Pas besoin de bibliothèques externes - utilisez simplement les chaînes de modèle ES6 :

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

Vanilla JS n'est PAS ES6. Mais j'aime bien votre exemple.
RyanNerd

8
@RyanNerd Vous voulez dire "ES6 n'est pas vanille JS"? Quoi qu'il en soit, car vanilla js signifie javascript sans aucun framework. ES6 est une nouvelle version de javascript. - stackoverflow.com/a/20435685/5111113
Huw Davies

Pas une mauvaise réponse mais pourrait être beaucoup améliorée. Par exemple, tout le monde a ajouté des exemples sur les États.
JGallardo

10

Peut-être que les noms de classe peuvent vous aider.

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

1
Pouvez-vous rendre cet exemple plus utilisable.
JGallardo

9

Je ne pense pas que nous ayons besoin d'utiliser un package externe pour simplement ajouter plusieurs classes.

J'utilise personnellement

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

ou

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

le second au cas où vous auriez besoin d'ajouter ou de supprimer des classes de façon conditionnelle.


1
cela n'ajoutera qu'une seule classe dans les deux cas.
TrickOrTreat

6

En ajoutant simplement, nous pouvons filtrer les chaînes vides.

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

6

Vous pouvez créer un élément avec plusieurs noms de classe comme celui-ci, j'ai essayé ces deux façons, son bon fonctionnement ...

Si vous importez un fichier CSS, vous pouvez suivre cette procédure: Méthode 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>
    );
  }
}

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

**

Si vous appliquez css en interne:

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

Vous pouvez effectuer les opérations suivantes:

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

Une solution courte et simple, j'espère que cela vous aidera.



4

Tard dans la fête, mais pourquoi utiliser un tiers pour un problème aussi simple?

Vous pouvez soit le faire comme l'a mentionné @Huw Davies - la meilleure façon

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

Les deux sont bons. Mais l'écriture peut devenir complexe pour une grande application. Pour le rendre optimal, je fais les mêmes choses ci-dessus mais je le mets dans une classe d'aide

L'utilisation de ma fonction d'aide ci-dessous, me permet de garder la logique séparée pour les modifications futures, et me donne également plusieurs façons d'ajouter les classes

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

ou

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

Ceci est ma fonction d'aide ci-dessous. Je l'ai mis dans un helper.js où je garde toutes mes méthodes courantes. Étant une fonction aussi simple, j'ai évité d'utiliser une tierce partie pour garder le contrôle

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

3

Vous pouvez utiliser des tableaux puis les joindre en utilisant l'espace.

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

Cela se traduira par:

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

3

Je sais que c'est une réponse tardive, mais j'espère que cela aidera quelqu'un.

Considérez que vous avez défini les classes suivantes dans un fichier css « primaire », « font-i », « font-xl »

  • La première étape serait d'importer le fichier CSS.
  • alors

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

ferait l'affaire!

Pour plus d'informations: https://www.youtube.com/watch?v=j5P9FHiBVNo&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=20


3

pour plus de classes en ajoutant

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

2

Utilisation de l'exemple TodoTextInput.js de 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} />
    )
  } 

remplacer les noms de classe par du code js ordinaire vanilla ressemblera à ceci:

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

Si vous n'avez pas envie d'importer un autre module, cette fonction fonctionne comme le classNamesmodule.

function classNames(rules) {
    var classes = ''

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

    return classes
} 

Vous pouvez l'utiliser comme ceci:

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

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

Pourquoi utiliser des fermetures si vous pouvez faire de même avec la carte ou réduire? function classNames(rules) { return Object.entries(rules) .reduce( (arr, [cls, flag]) => { if (flag) arr.push(cls); return arr }, [] ).join(" ") }
Евгений Савичев

1

C'est ce que je fais:

Composant:

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

Composant appelant:

<Button className = 'hashButton free anotherClass' />

1

J'utilise React 16.6.3 et @Material UI 3.5.1, et je peux utiliser des tableaux dans className comme className={[classes.tableCell, classes.capitalize]}

Donc, dans votre exemple, ce qui suit serait similaire.

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

C'est ce que je faisais (bien qu'il n'y ait pas de MUI) et ne fonctionne pas, applique uniquement la première classe - pas d'avertissement ni de plainte.
Juan Lanus

1

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

importer classNames à partir de 'classnames';

  1. Peut utiliser plusieurs classes en utilisant des comas séparés:

    <li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>
  2. Peut utiliser plusieurs classes en utilisant des comas séparés avec condition:

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

L'utilisation de tableaux comme accessoires pour classNames fonctionnera également, mais donne un avertissement, par exemple

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


0

J'utilise le package 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
})} />

Vous pouvez ajouter des classes dans n'importe quel format (tableau, objet, argument). Toutes les valeurs véridiques des tableaux ou des arguments et des clés dans les objets qui sont égales pour trueêtre fusionnées ensemble.

par exemple:

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

Je bind classNamesau module CSS importé dans le composant.

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

classnamesdonne la possibilité de déclarer classNamepour un élément React d'une manière déclarative.

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

Je l'utilise habituellement comme ceci: (dans votre cas)

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

Quand il s'agit de JSX et (généralement) nous avons du json ... que vous bouclez ... composant . map , plus quelques conditions pour vérifier si la propriété json existe pour rendre le nom de la classe en fonction de la valeur de la propriété de JSON. Dans l'exemple ci-dessous, component_color et component_dark_shade sont des propriétés de component.map ()

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

Sortie: <div class="component no-color light" .... Ou: en <div class="component blue dark" ....fonction des valeurs de la carte ...


0

Lorsque j'ai plusieurs classes différentes, j'ai trouvé les éléments suivants utiles.

Le filtre supprime toutes les nullvaleurs et la jointure place toutes les valeurs restantes dans une chaîne séparée par des espaces.

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

<button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}>
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.