Como adicionar várias classes a um componente ReactJS


346

Eu sou novo no ReactJS e JSX e estou tendo um pequeno problema com o código abaixo.

Estou tentando adicionar várias classes ao classNameatributo em cada um li:

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

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

Encontrei uma resposta rápida aqui stackoverflow.com/a/36209517/4125588 , basta usar JavaScript para ingressar nesta classe, estática ou dinâmica, com o operador '+', lembre-se de inserir '' antes das classes, exceto a primeira, como a real classe em HTML deve ser como 'ab c', também espaço entre eles.
Fadeoc Khaos 08/08/19


11
Por que não trabalhaclassNames={{foo: true, bar: true, baz: false}} e classNames={["foo", "bar"]}apenas trabalha ?
Peter V. Mørch

Respostas:


221

Uso nomes de classe quando há uma quantidade razoável de lógica necessária para decidir (não) o uso das classes. Um exemplo excessivamente simples :

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

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

Dito isto, se você não deseja incluir uma dependência, há respostas melhores abaixo.


188
Isso é muito ruim você tinha que trazer uma biblioteca de nomes de classes apenas para adicionar duas classes para um elemento :(
user959690

4
@ user959690 Este é um exemplo. Essa biblioteca é muito boa quando você faz muito essas coisas e tem uma lógica complexa sobre quando as classes precisam ser aplicadas ou não. Se você está fazendo algo simples, use modelos, mas todos os casos são diferentes e o leitor deve escolher a ferramenta certa para o trabalho.
Jack

7
@ user959690 Vale a pena notar que agora ele é instalado pelo NPM ao usar o Webpack , para import classNames from 'classnames'ser usado em um componente className={classNames(classes.myFirstClass, classes.mySecondClass)} .
Hooligancat

5
Não há necessidade de usar uma biblioteca externa, veja minha resposta abaixo.
Huw Davies

11
A biblioteca tem outras vantagens: 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 5/11/19

395

Eu uso ES6 literais de modelo . Por exemplo:

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

E então apenas renderize:

<input className={classes} />

Versão de uma linha:

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

157
Também:<input className={`class1 ${class2}`}>
Cody Moniz

3
@unyo Por favor, poste seu comentário como resposta, para que eu possa votá-lo novamente. Isso merece muito. Eu estive procurando por 1 hora por algo tão fácil como isso, e agora acho isso enterrado como um comentário. Obrigado.
Souvik Ghosh

Isso resulta em <input class=" form-control input-lg round-lg" />. Anote o espaço extra no começo. Isso é válido, mas feio. As perguntas frequentes sobre React
Nakedible

Não consigo entender por que você importaria uma biblioteca (como na resposta aceita) para apenas definir algumas classes que podem ser definidas usando o Vanilla JavaScript, que é uma solução mais eficiente, mais limpa e legível de qualquer maneira.
Marcus Parsons

2
Essa é a resposta correta. Usar uma dependência para isso, como sugerido na resposta "correta", é um exagero.
TheDarkIn1978 04/04/19

171

Basta usar o JavaScript.

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

Se você deseja adicionar chaves e valores baseados em classes em um objeto, pode usar o seguinte:

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 ainda mais simples:

const isEnabled = true;
const isChecked = false;

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

Aqui está a linha que funcionou para mim:className={['terra-Table', medOrder.resource.status]}
Doug Wilhelm

11
@DougWilhelm Acho que não funciona. Chama implicitamente toString e cria uma lista de classes separada por vírgula. github.com/facebook/react/issues/3138
0xcaff

6
Boa idéia de usá- className={[listOfClasses].join(' ')}lo está funcionando para mim obrigado!
Ala Eddine Jebali

98

Concat

Não precisa ser extravagante, estou usando módulos CSS e é fácil

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

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

Isso resultará em:

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

Em outras palavras, ambos os estilos

Condicionais

Seria fácil usar a mesma idéia com if's

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

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

11
Isso funcionou para mim, juntamente com os nomes '-', ou seja: <nav className = {styles.navbar + "" + styles ['navbar-default']}>
Flinkman

LOL, eu quebro minha cabeça e a resposta é simples: D. Btw este trabalho alsow com CSS Módulo Carregador
GusDeCooL

O problema é que você não pode ter classes opcionais (se indefinidas, elas não serão adicionadas); portanto, depende de você ter certeza de que sua classe não é nula (não opcional). No caso de opcional, não há melhor do que um auxiliar como classes (). podemos usar um ternário com modelos como o className={controle deslizante $ {className? `$ {className} : ''}}` `. Mas é muito. [nota: 'algo' + indefinido = 'algo sublinhado'. Js conversão dinâmica.
Mohamed Allal

Claro que você pode, basta declarar uma variável acima e usá-lo condicionalmente :)
Jamie Hutber

42

Isso pode ser alcançado com os literais do modelo ES6:

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

11
isso quase funcionou para mim, eu apenas tive que interpolar a classe1 também e não haver mais erros, então fica assim <input className={`${class1} ${class2}`}>
Kingston Fortune

35

Você pode criar um elemento com vários nomes de classe como este:

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

Naturalmente, você pode usar uma sequência contendo os nomes das classes e manipulá-las para atualizar os nomes das classes do elemento.

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

11
Você testou isso? Eu fiz :) #
raven

Sim eu fiz. Na verdade, estou usando-o com bastante frequência, mas apenas vi e corrigi um erro de digitação. Obviamente, a string que contém os nomes das classes na primeira linha deve ser criada usando em "vez de '. Me desculpe por isso.
nightlyop 30/05

20

É assim que você pode fazer isso com o ES6:

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

Você pode listar várias classes e condições e também pode incluir classes estáticas. Não é necessário adicionar uma biblioteca adicional.

Boa sorte ;)


2
Isso resulta em HTML muito feio, considerando todo o espaço em branco extra.
Nakedible 20/10/19

2
Não é necessário escrever assim. Este é apenas um exemplo que explica melhor a solução. E sempre na produção que tem a versão minified :)
Hristo Eftimov

18

JS de baunilha

Não há necessidade de bibliotecas externas - basta usar as strings de modelo ES6 :

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

JS de baunilha NÃO é ES6. Mas eu gosto do seu exemplo.
RyanNerd

8
@RyanNerd Você quer dizer "ES6 não é JS de baunilha"? Enfim, é porque vanilla js significa javascript sem nenhuma estrutura. ES6 é uma versão mais recente do javascript. - stackoverflow.com/a/20435685/5111113
Huw Davies

Não é uma resposta errada, mas poderia ser melhorada muito. Por exemplo, todos os outros adicionaram exemplos sobre estados.
JGallardo 15/10/19

10

Talvez os nomes de classe possam ajudá-lo.

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

11
Você pode tornar este exemplo mais utilizável.
JGallardo 16/09/19

9

Eu não acho que precisamos usar um pacote externo apenas para adicionar várias classes.

Eu pessoalmente uso

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

ou

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

o segundo caso você precise adicionar ou remover classes condicionalmente.


11
isso adicionará apenas uma classe de qualquer maneira.
TrickOrTreat

6

Apenas adicionando, podemos filtrar as strings vazias.

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

6

Você pode criar um elemento com vários nomes de classe como este, tentei isso nos dois sentidos, está funcionando bem ...

Se você estiver importando algum css, poderá seguir este caminho: Caminho 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>
    );
  }
}

caminho 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 você estiver aplicando css como 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

Você pode fazer o seguinte:

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

Uma solução curta e simples, espero que ajude.



4

Tarde para a festa, mas por que usar terceiros para um problema tão simples?

Você poderia fazê-lo como @Huw Davies mencionou - a melhor maneira

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

Ambos são bons. Mas a escrita pode se tornar complexa para um aplicativo grande. Para torná-lo ideal, eu faço o mesmo acima, mas coloco em uma classe auxiliar

Usar minha função auxiliar abaixo, permite manter a lógica separada para edição futura e também oferece várias maneiras de adicionar as classes

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

ou

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

Esta é a minha função auxiliar abaixo. Coloquei-o em um helper.js, onde mantenho todos os meus métodos comuns. Sendo uma função tão simples, evitei usar terceiros para manter o controle

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

3

Você pode usar matrizes e juntá-las usando espaço.

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

Isso resultará em:

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

3

Sei que esta é uma resposta tardia, mas espero que isso ajude alguém.

Considere que você definiu as seguintes classes em um arquivo css ' primário ', ' font-i ', ' font-xl '

  • O primeiro passo seria importar o arquivo CSS.
  • Então

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

faria o truque!

Para mais informações: https://www.youtube.com/watch?v=j5P9FHiBVNo&list=PLC3y8-rFHvwgg3vaYJgHGnModB54rxOk3&index=20


3

para mais aulas adicionando

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

2

Usando o exemplo TodoTextInput.js do 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} />
    )
  } 

a substituição de nomes de classe por código simples vanilla js terá a seguinte aparência:

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 você não deseja importar outro módulo, esta função funciona como o classNamesmódulo.

function classNames(rules) {
    var classes = ''

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

    return classes
} 

Você pode usá-lo assim:

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

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

Por que usar encerramentos se você pode fazer o mesmo com o mapa ou reduzir? function classNames(rules) { return Object.entries(rules) .reduce( (arr, [cls, flag]) => { if (flag) arr.push(cls); return arr }, [] ).join(" ") }
Евгений Савичев

1

Isto é o que eu faço:

Componente:

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

Componente de chamada:

<Button className = 'hashButton free anotherClass' />

1

Estou usando o React 16.6.3 e o @Material UI 3.5.1 e posso usar matrizes em className como className={[classes.tableCell, classes.capitalize]}

Portanto, no seu exemplo, o seguinte seria semelhante.

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

Isto é o que eu estava fazendo (embora sem MUI) e não funciona, apenas aplica a primeira classe - sem aviso ou reclamação.
Juan Lanus

1

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

importar classNames de 'classnames';

  1. Pode usar várias classes usando comas separados:

    <li className={classNames(classes.tableCellLabel, classes.tableCell)}>Total</li>
  2. Pode usar várias classes usando vírgulas separadas com a condição:

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

Usar array como adereços para classNames também funcionará, mas fornece aviso, por exemplo

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


0

Eu uso o pacote 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
})} />

Você pode adicionar classes em qualquer formato (matriz, objeto, argumento). Todos os valores reais de matrizes ou argumentos e chaves em objetos iguais atrue serem mesclados.

por exemplo:

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 classNamespara o módulo css importado para o componente.

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

classnames dá a capacidade de declarar className um elemento React de maneira declarativa.

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

Eu costumo usá-lo assim: (no seu caso)

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

Quando se trata de JSX e (geralmente), temos alguns json ... do que você loop-lo ... componente . map , mais algumas condicionais para verificar se a propriedade json existe para renderizar o nome da classe, dependendo do valor da propriedade de JSON. No exemplo abaixo component_color e component_dark_shade são propriedades de component.map ()

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

Saída: <div class="component no-color light" .... Ou: <div class="component blue dark" ....dependendo dos valores do mapa ...


0

Quando tenho muitas classes diferentes, considero útil o seguinte.

O filtro remove qualquer um dos nullvalores e a união coloca todos os valores restantes em uma sequência separada por espaço.

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

<button className={buttonClasses} onClick={onClick} disabled={disabled ? disabled : false}>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.