Como adicionar várias classes em Material UI usando os adereços de classes

95

Usando o método css-in-js para adicionar classes a um componente react, como adiciono vários componentes?

Aqui está a variável classes:

const styles = theme => ({
 container: {
  display: 'flex',
  flexWrap: 'wrap'
},
 spacious: {
  padding: 10
},
});

Aqui está como eu usei:

    return (
     <div className={ this.props.classes.container }>

O classNamesprocedimento acima funciona, mas existe uma maneira de adicionar ambas as classes, sem usar o pacote npm? Algo como:

     <div className={ this.props.classes.container + this.props.classes.spacious}>
q3e
fonte
3
Talvez esteja faltando alguma coisa, mas você não pode simplesmente fazer <div className = "container spacious"> Por que você precisa passar isso como uma propriedade?
Leo Farmer
2
você está apenas perdendo um espaço entre os dois classNames.
Shanimal
Sim, como afirmado acima, você só precisa concatá-las corretamente com um espaço no meio! Não há necessidade de pacotes adicionais.
Taylor A. Leach

Respostas:

191

você pode usar interpolação de string:

<div className={`${this.props.classes.container} ${this.props.classes.spacious}`}>
Klugjo
fonte
5
e lembre-se de não adicionar vírgulas entre as aulas! Eu fiz por engano e o primeiro quebrou silenciosamente sem perceber por um tempo
Pere
E deve haver um espaço entre as aulas
Yoel
48

você pode instalar este pacote

https://github.com/JedWatson/classnames

e então usá-lo assim

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'

// lots of arguments of various types
classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'

// other falsy values are just ignored
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
Mini
fonte
3
Esta é a abordagem que o Material-UI usa em alguns de seus exemplos e funciona bem, então eu recomendo isso.
Craig Myles,
2
Esta deve ser a resposta aceita. Funciona conforme o esperado
Howie
2
Tenho usado essa abordagem também. Útil não apenas por ter vários nomes de classe, mas também por torná-los condicionais.
mouthzipper
4
@material-ui/coreagora depende de clsx, então se você não quiser aumentar o tamanho do seu pacote, você deve usar isso - npmjs.com/package/clsx
Wayne Bloss
37

Você pode usar o clsx . Percebi que é usado nos exemplos de botões MUI

Primeiro instale:

npm install --save clsx

Em seguida, importe-o em seu arquivo de componente:

import clsx from 'clsx';

Em seguida, use a função importada em seu componente:

<div className={ clsx(classes.container, classes.spacious)}>

Razzlero
fonte
5
clsxpacote é menor que classnames, então eu prefiro esta solução
Hoang Trinh
2
clsx está incluído na IU de material, portanto, é mais preferido do que
nomes
1
Per comentário Wayne Bloss' abaixo resposta menos ideal do Mini: @material-ui/core now depends on clsx, so if you don't want to increase your bundle size you'll want to use that instead. Então, 1 para esta resposta.
cssyphus
19

Para ter várias classes aplicadas a um componente, agrupe as classes que gostaria de aplicar em classNames.

Por exemplo, em sua situação, seu código deve ser assim,

import classNames from 'classnames';

const styles = theme => ({
  container: {
    display: "flex",
    flexWrap: "wrap"
  },
  spacious: {
    padding: 10
  }
});

<div className={classNames(classes.container, classes.spacious)} />

Certifique-se de importar classNames !!!

Dê uma olhada na documentação da interface do usuário onde eles usam várias classes em um componente para criar um botão personalizado

will92
fonte
9

Você também pode usar a propriedade extend (o plugin jss-extend é habilitado por padrão):

const styles = theme => ({
  container: {
    display: 'flex',
    flexWrap: 'wrap'
  },
  spaciousContainer: {
    extend: 'container',
    padding: 10
  },
});

// ...
<div className={ this.props.classes.spaciousContainer }>
VaclavSir
fonte
2
Infelizmente, não está mais habilitado por padrão ... vote para habilitar aqui
egerardus
7

Acho que isso vai resolver o seu problema:

const styles = theme => ({
 container: {
  display: 'flex',
  flexWrap: 'wrap'
},
 spacious: {
  padding: 10
},
});

e no componente de reação:

<div className={`${classes.container} ${classes.spacious}`}>
Kalim M Vazir
fonte
6

Sim, jss-composes fornece isto:

const styles = theme => ({
 container: {
  display: 'flex',
  flexWrap: 'wrap'
},
 spacious: {
  composes: '$container',
  padding: 10
},
});

E então você apenas usa classes.spacious.

Oleg Isonen
fonte
ao usar vários nomes de classe usando compose, não funciona. codesandbox.io/s/practical-cohen-l6qt5?file=/src/text.js
user970780
2

classNames o pacote também pode ser usado tão avançado quanto:

import classNames from 'classnames';

var arr = ['b', { c: true, d: false }];
classNames('a', arr); // => 'a b c'

let buttonType = 'primary';
classNames({ [`btn-${buttonType}`]: true }); // => 'btn-primary'
Hasan Sefa Ozalp
fonte
show error webpack build: Módulo não encontrado: Erro: Não é possível resolver 'classnames' em
Pranay Soni
1

Você pode adicionar várias classes de string e classes de variáveis ​​ou classes de adereços ao mesmo tempo desta forma

className={`${classes.myClass}  ${this.props.classes.myClass2} MyStringClass`}

três aulas ao mesmo tempo

Muzamil301
fonte
-1

Se você deseja atribuir vários nomes de classe ao seu elemento, pode usar matrizes .

Portanto, em seu código acima, se this.props.classes resolver para algo como ['container', 'spacious'], ou seja, se

this.props.classes = ['container', 'spacious'];

você pode simplesmente atribuí-lo a div como

<div className = { this.props.classes.join(' ') }></div>

e o resultado será

<div class='container spacious'></div>
Praym
fonte
tem certeza de que classes nomeadas separadas por ,no resultado
Pardeep Jain
8
Não sei por que essa é a resposta aceita, @Glauber Ramos está certo, a IU de material não funciona assim.
timotgl
-1

Como já mencionado, você pode usar interpolação de string

className={`${this.props.classes.container}  ${this.props.classes.spacious}`}

E você pode tentar a classnamesbiblioteca, https://www.npmjs.com/package/classnames

Nemus
fonte
Ambas as partes da sua resposta foram fornecidas anteriormente por outros membros. Tudo o que você fez foi repeti-los em uma única resposta. -1 (Sugiro que você exclua esta resposta e recupere seus 2 pontos)
cssyphus