Передача имен классов для реагирующих компонентов


98

Я пытаюсь передать имя класса компоненту реакции, чтобы изменить его стиль, и, похоже, не могу работать:

class Pill extends React.Component {

  render() {

    return (
      <button className="pill {this.props.styleName}">{this.props.children}</button>
    );
  }

}

<Pill styleName="skill">Business</Pill>

Я пытаюсь изменить стиль таблетки, передав имя класса, имеющего соответствующий стиль. Я новичок в React, поэтому, возможно, я делаю это неправильно. Благодарность

Ответы:


134

В React, когда вы хотите передать интерпретируемое выражение, вам нужно открыть пару фигурных скобок. Пытаться:

render () {
  return (
    <button className={`pill ${ this.props.styleName }`}>
      {this.props.children}
    </button>
  );
}

Использование пакета npm classnames

import classnames from 'classnames';

render() {
  return (
    <button className={classnames('pill', this.props.styleName)}>
      {this.props.children}
    </button>
  );
}

3
Почему лучше: производительность? читаемость? другие? Литеральные строки (ваш первый пример) являются частью ES6, так что это стандарт. Это делает меньше кода и избегает импорта. Мне так кажется лучше, но у другого решения могут быть аргументы.
Мос

2
В приведенном выше примере вы абсолютно правы, лучше использовать строки ES6. Я бы сказал, что имена классов лучше с точки зрения читаемости и СУХОЙ, когда вам нужно иметь дело с условными операторами, например, в readme имен классов показывает github.com/JedWatson/classnames#usage-with-reactjs .
gcedo 02

{} Фигурные скобки, [] квадратные скобки, () круглые скобки - вам не нужно говорить «фигурные скобки», потому что фигурные скобки по определению.
Рекс Странный,

25

Просто для справки для компонентов без состояния:

// ParentComponent.js
import React from 'react';
import { ChildComponent } from '../child/ChildComponent';

export const ParentComponent = () =>
  <div className="parent-component">
    <ChildComponent className="parent-component__child">
      ...
    </ChildComponent>
  </div>

// ChildComponent.js
import React from 'react';

export const ChildComponent = ({ className, children }) =>
  <div className={`some-css-className ${className}`}>
    {children}
  </div>

Окажут:

<div class="parent-component">
  <div class="some-css-className parent-component__child">
    ...
  </div>
</div>

Не следует ли, добавляя свойство className к компоненту React, передавать это className первому элементу контейнера вместо передачи его в качестве свойства имени?
theSereneRebel

1
@theSereneRebel Нет, это не так. См. Пример здесь: codesandbox.io/s/clever-knuth-enyju
Махди

@theSereneRebel Хорошо это или плохо - это уже другая тема.
Махди

18

pill ${this.props.styleName} получит "pill undefined", если вы не установите реквизит

я предпочитаю

className={ "pill " + ( this.props.styleName || "") }

или

className={ "pill " + ( this.props.styleName ? this.props.styleName : "") }

7

Для всех, кого это интересует, я столкнулся с этой же проблемой при использовании модулей css и реагировании модулей css .

Большинство компонентов имеют связанный стиль модуля css, и в этом примере моя кнопка имеет собственный файл css, как и родительский компонент Promo . Но я хочу передать некоторые дополнительные стили кнопке из Promo.

Итак, styleспособная кнопка выглядит так:

Button.js

import React, { Component } from 'react'
import CSSModules from 'react-css-modules'
import styles from './Button.css'

class Button extends Component {

  render() {

    let button = null,
        className = ''

    if(this.props.className !== undefined){
        className = this.props.className
    }

    button = (
      <button className={className} styleName='button'>
        {this.props.children}
      </button>
    )

    return (
        button
    );
  }
};

export default CSSModules(Button, styles, {allowMultiple: true} )

В указанном выше компоненте Button стили Button.css обрабатывают общие стили кнопок. В этом примере просто .buttonкласс

Затем в моем компоненте, где я хочу использовать кнопку , и я также хочу изменить такие вещи, как положение кнопки, я могу установить дополнительные стили Promo.cssи передать их как classNameопору. В этом примере снова называется .buttonclass. Я мог бы назвать это как угодно, например promoButton.

Конечно, с модулями css этот класс будет, .Promo__button___2MVMDтогда как кнопка будет чем-то вроде.Button__button___3972N

Promo.js

import React, { Component } from 'react';
import CSSModules from 'react-css-modules';
import styles from './Promo.css';

import Button from './Button/Button'

class Promo extends Component {

  render() {

    return (
        <div styleName='promo' >
          <h1>Testing the button</h1>
          <Button className={styles.button} >
            <span>Hello button</span>
          </Button>
        </div>
      </Block>
    );
  }
};

export default CSSModules(Promo, styles, {allowMultiple: true} );

Обновление 2018: использование propTypes и defaultProps для обработки случаев, когда свойство может существовать или не существовать, является более чистым и предпочтительным.
BrianHVB

6

Как утверждали другие, используйте интерпретируемое выражение с фигурными скобками.

Но не забудьте установить значение по умолчанию.
Другие предлагали использовать оператор OR для установки пустой строки if undefined.

Но еще лучше было бы объявить свой реквизит.

Полный пример:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class Pill extends Component {

  render() {

    return (
      <button className={`pill ${ this.props.className }`}>{this.props.children}</button>
    );
  }

}

Pill.propTypes = {
  className: PropTypes.string,
};

Pill.defaultProps = {
  className: '',
};

4

Вы можете добиться этого, «интерполируя» имя класса, переданное от родительского компонента дочернему компоненту, используя this.props.className. Пример ниже:

export default class ParentComponent extends React.Component {
  render(){
    return <ChildComponent className="your-modifier-class" />
  }
}

export default class ChildComponent extends React.Component {
  render(){
    return <div className={"original-class " + this.props.className}></div>
  }
}

1

В React 16.6.3 и @Material UI 3.5.1 я использую массивы в className, например className={[classes.tableCell, classes.capitalize]}

В вашем случае попробуйте что-то вроде следующего.

class Pill extends React.Component {
    render() {
        return (
           <button className={['pill', this.props.styleName]}>{this.props.children}</button>
        );
    }
}

0

Благодаря поддержке React интерполяции строк вы могли сделать следующее:

class Pill extends React.Component {
    render() {
       return (
          <button className={`pill ${this.props.styleName}`}>{this.props.children}</button>
       );
    }
}


0

В Typescript вам нужно установить типы HTMLAttributesи React.FunctionComponent.

В большинстве случаев вам нужно будет расширить его до другого интерфейса или типа.

const List: React.FunctionComponent<ListProps &
  React.HTMLAttributes<HTMLDivElement>> = (
  props: ListProps & React.HTMLAttributes<HTMLDivElement>
) => {
  return (
    <div className={props.className}>
      <img className="mr-3" src={props.icon} alt="" />
      {props.context}
    </div>
  );
};

interface ListProps {
  context: string;
  icon: string;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.