Как применить стили на основе реквизита?

Я использую React и Material-ui, и в настоящее время делаю что-то вроде приведенного ниже кода.
Есть ли способ лучше?

Например, существует ли функция, которая позволяет вам получить доступ к «реквизитам» в jss-объекте «стилей» под компонентом, который в конечном итоге вводится в компонент с помощью withStyles () без необходимости выполнять все эти уродливые встроенные стили?

import React from 'react';
import {
  MaterialComponentOne,
  MaterialComponentTwo,
  MaterialComponentThree,
} from '@material-ui/core';

function MyPureComponent(props) {
  return (
    <MaterialComponentOne
      style={
        props.type === 'secondary'
          ? {
              css_property: 'css_value1',
            }
          : {
              css_property: 'css_value2',
            }
      }
      className={props.classes.MaterialComponentOne}
      position="static"
    >
      <MaterialComponentTwo>
        <MaterialComponentThree
          style={
            props.type === 'secondary'
              ? {
                  css_property: 'css_value1',
                }
              : {
                  css_property: 'css_value2',
                }
          }
          variant="title"
          className={props.classes.MaterialComponentThree}
        >
          {props.title}
        </MaterialComponentThree>
      </MaterialComponentTwo>
    </MaterialComponentOne>
  );
}

const styles = {
  MaterialComponentOne: {
    css_property: 'css_value',
    css_property: 'css_value',
  },
  MaterialComponentTwo: {
    css_propery: 'css_value',
  },
};

export default withTheme()(withStyles(styles)(MyPureComponent));

Благодарю.


person Neilson Gamble    schedule 10.08.2018    source источник
comment
Почему у вас есть в объекте стиля MaterialComponentOne два свойства css с одним и тем же ключом?   -  person ChrisR    schedule 10.08.2018


Ответы (2)


Вы можете использовать библиотеку clsx, которая поставляется с пользовательским интерфейсом материала или classnames библиотека для условного объединения classNames вместе. Пример ниже показан с использованием библиотеки имен классов, вы также можете использовать библиотеку clsx для достижения того же результата.

import React from 'react';
import {
  MaterialComponentOne,
  MaterialComponentTwo,
  MaterialComponentThree,
} from '@material-ui/core';
import classNames from "classnames"

function MyPureComponent(props) {
  return (
    <MaterialComponentOne
      position="static"
      className={classNames(
        props.classes.MaterialComponentOne, 
        {[props.classes.classOne]: props.type === 'secondary'}, 
        {[props.classes.classTwo]: props.type !== 'secondary'}
      )}

    >
      <MaterialComponentTwo>
        <MaterialComponentThree
          variant="title"
          className={classNames(
            props.classes.MaterialComponentThree, 
            {"props.classes.classOne": props.type === 'secondary'}, 
            {"props.classes.classTwo": props.type !== 'secondary'}
          )}
        >
          {props.title}
        </MaterialComponentThree>
      </MaterialComponentTwo>
    </MaterialComponentOne>
  );
}

const styles = {
  MaterialComponentOne: {
    css_property: 'css_value',
    css_property: 'css_value',
  },
  MaterialComponentTwo: {
    css_propery: 'css_value',
  },
  classOne: {
    css_property: 'css_value',
  },
  classTwo: {
    css_property: 'css_value'
  }
};

export default withTheme()(withStyles(styles)(MyPureComponent));



Использование


Функция classNames принимает любое количество аргументов, которые могут быть строкой или объектом. Аргумент 'foo' является сокращением от { foo: true}. Если значение, связанное с данным ключом, является ложным, этот ключ не будет включен в вывод.

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'
person Andrew Lam    schedule 10.08.2018
comment
Я предпочитаю это решение, поскольку id не вводит другой фреймворк стилей, например, styled-components. - person Ricovitch; 10.08.2018
comment
@Andrew, вы, вероятно, хотели использовать имена вычисляемых свойств, такие как {[props.classes.classOne]: true} вместо строки {props.classes.classOne: true} - person Idan Dagan; 10.08.2018
comment
Привет, @Idan Dagon, спасибо за предложение, но я не знаю различий между ними, не могли бы вы объяснить это? Спасибо :) - person Andrew Lam; 10.08.2018
comment
@AndrewLam просто запустите свой код и убедитесь, что у вас есть ошибка при использовании classNames. и прочтите о вычисленных именах свойств - person Idan Dagan; 13.08.2018
comment
@IdanDagan Спасибо за исправление и объяснение :) - person Andrew Lam; 16.12.2018

Вы можете использовать styled-components.

Пример на основе документов Адаптация на основе реквизита:

import styled from 'styled-components';

const Button = styled.button`
  background: ${props => props.primary ? 'palevioletred' : 'white'};
  color: ${props => props.primary ? 'white' : 'palevioletred'};
`;

function MyPureComponent(props) {
  return (
    <div>
      <Button>Normal</Button>
      <Button primary>Primary</Button>
    </div>
  );
}
person Idan Dagan    schedule 10.08.2018