Как добавить несколько классов в пользовательский интерфейс материалов с помощью свойств классов


92

Как добавить несколько компонентов с помощью метода css-in-js для добавления классов в компонент реакции?

Вот переменная классов:

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

Вот как я это использовал:

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

Вышеупомянутое работает, но есть ли способ добавить оба класса без использования classNamesпакета npm? Что-то типа:

     <div className={ this.props.classes.container + this.props.classes.spacious}>

3
Может быть, мне чего-то не хватает, но нельзя просто сделать <div className = "container large"> Зачем нужно передавать это как свойство?
Лео Фармер

2
вам просто не хватает пробела между двумя classNames.
Shanimal

Да, как указано выше, вам просто нужно правильно объединить классы вместе с пробелом между ними! Никаких дополнительных пакетов не требуется.
Тейлор А. Лич

Ответы:


180

вы можете использовать строковую интерполяцию:

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

5
и помните, что нельзя добавлять запятые между классами! Я сделал это по ошибке, и первый сломался тихо, какое-то время не замечая
Pere

И между классами должен быть промежуток
Йоэль

49

вы можете установить этот пакет

https://github.com/JedWatson/classnames

а затем используйте это так

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'

3
Это подход, который Material-UI использует в некоторых из своих примеров, и он хорошо работает, поэтому я бы рекомендовал его.
Крэйг Майлз

2
Это должен быть принятый ответ. Работает как ожидалось
Howie

2
Я тоже использовал этот подход. Полезно не только для того, чтобы иметь несколько имен классов, но и для того, чтобы сделать их условными.
Mouthzipper

4
@material-ui/coreтеперь зависит от clsx, поэтому, если вы не хотите увеличивать размер пакета, вы захотите использовать его вместо этого - npmjs.com/package/clsx
Wayne

34

Вы можете использовать clsx . Я заметил, что это используется в примерах кнопок MUI

Сначала установите его:

npm install --save clsx

Затем импортируйте его в свой файл компонента:

import clsx from 'clsx';

Затем используйте импортированную функцию в своем компоненте:

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


5
clsxpackage меньше чем classnames, поэтому я предпочитаю это решение
Hoang Trinh

2
clsx включен в пользовательский интерфейс материалов, поэтому он более предпочтителен, чем
имена классов

1
За комментарием Wayne Блосс ниже менее оптимальный ответ 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. Итак, +1 за этот ответ.
cssyphus

20

Чтобы к компоненту применялось несколько классов, оберните классы, которые вы хотите применить, в classNames.

Например, в вашей ситуации ваш код должен выглядеть так:

import classNames from 'classnames';

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

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

Убедитесь, что вы импортируете classNames !!!

Взгляните на документацию по пользовательскому интерфейсу материалов, где они используют несколько классов в одном компоненте для создания настраиваемой кнопки.


9

Вы также можете использовать свойство extend ( плагин jss-extend включен по умолчанию):

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

// ...
<div className={ this.props.classes.spaciousContainer }>

2
К сожалению, по умолчанию больше не включен ... проголосуйте за включение здесь
egerardus

7

Думаю, это решит вашу проблему:

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

и в реакционном компоненте:

<div className={`${classes.container} ${classes.spacious}`}>

6

Да, jss-composes предоставляет вам это:

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

И тогда вы просто используете classes.spacious.


при использовании нескольких имен классов с помощью compose это не работает. codeandbox.io/s/practical-cohen-l6qt5?file=/src/text.js
user970780

2

classNames пакет также можно использовать как расширенный:

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'

показать ошибку сборки webpack: Модуль не найден: Ошибка: не удается разрешить «имена классов» в
Pranay Soni

1

Таким образом вы можете одновременно добавить несколько строковых классов и классов переменных или классов свойств.

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

три класса одновременно


-1

Если вы хотите присвоить своему элементу несколько имен классов , вы можете использовать массивы .

Итак, в приведенном выше коде, если this.props.classes преобразуется во что-то вроде ['container', 'large'], т.е. если

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

вы можете просто назначить его div как

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

и результат будет

<div class='container spacious'></div>

Вы уверены, что ,в результате классы названы разделенными
символом

8
Не уверен, почему это принятый ответ, @Glauber Ramos прав, Material UI так не работает.
timotgl

-1

Как уже упоминалось, вы можете использовать интерполяцию строк

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

И вы можете попробовать classnamesбиблиотеку https://www.npmjs.com/package/classnames


Обе части вашего ответа ранее были предоставлены другими участниками. Все, что вы сделали, это повторили их в единственном ответе. -1 (Предлагаю удалить этот ответ и восстановить свои 2
балла
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.