Übergeben von Klassennamen, um auf Komponenten zu reagieren

91

Ich versuche, einen Klassennamen an eine Reaktionskomponente zu übergeben, um deren Stil zu ändern, und kann anscheinend nicht funktionieren:

class Pill extends React.Component {

  render() {

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

}

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

Ich versuche, den Stil der Pille zu ändern, indem ich den Namen der Klasse übergebe, die den jeweiligen Stil hat. Ich bin neu in React, also mache ich das vielleicht nicht richtig. Vielen Dank

Hilarl
quelle

Antworten:

130

Wenn Sie in React einen interpretierten Ausdruck übergeben möchten, müssen Sie ein Paar geschweifte Klammern öffnen. Versuchen:

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

Verwenden des npm-Pakets für Klassennamen

import classnames from 'classnames';

render() {
  return (
    <button className={classnames('pill', this.props.styleName)}>
      {this.props.children}
    </button>
  );
}
gcedo
quelle
3
Warum ist es besser: Leistung? Lesbarkeit? Andere ? Literale Zeichenfolgen (Ihr erstes Beispiel) sind Teil von ES6, daher ist dies ein Standard. Es macht weniger Code und vermeidet einen Import. Es fühlt sich für mich besser an, aber die andere Lösung kann Argumente haben.
Mose
2
Im obigen Beispiel haben Sie absolut Recht, es ist besser, ES6-Zeichenfolgen zu verwenden. Ich würde sagen, Klassennamen sind in Bezug auf Lesbarkeit und DRY besser, wenn Sie sich mit Bedingungen befassen müssen, wie in den Klassennamen readme zeigt github.com/JedWatson/classnames#usage-with-reactjs .
Gcedo
{} Klammern, [] Klammern, () Klammern - Sie müssen nicht "geschweifte Klammern" sagen, da Klammern per Definition geschweifte Klammern sind.
Rex der Seltsame
21

Nur als Referenz für zustandslose Komponenten:

// 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>

Wird rendern:

<div class="parent-component">
  <div class="some-css-className parent-component__child">
    ...
  </div>
</div>
Mahdi
quelle
Sollte das Hinzufügen einer className-Requisite zu einer React-Komponente diesen className nicht an das erste Containerelement übergeben, anstatt ihn als name-Requisite zu übergeben?
theSereneRebel
@theSereneRebel Nein, das tut es nicht. Sehen Sie hier ein Beispiel: Codesandbox.io/s/clever-knuth-enyju
Mahdi
@theSereneRebel Ob das gut ist oder nicht, ist ein anderes Thema.
Mahdi
17

pill ${this.props.styleName} wird "Pille undefiniert" erhalten, wenn Sie die Requisiten nicht einstellen

ich bevorzuge

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

oder

className={ "pill " + ( this.props.styleName ? this.props.styleName : "") }
Gehälter
quelle
7

Für alle Interessierten stieß ich auf dasselbe Problem, wenn ich CSS-Module verwendete und CSS-Module reagierte .

Den meisten Komponenten ist ein CSS-Modulstil zugeordnet. In diesem Beispiel verfügt mein Button über eine eigene CSS-Datei, ebenso wie die übergeordnete Promo- Komponente. Aber ich möchte Button von Promo einige zusätzliche Stile übergeben

Der stylefähige Button sieht also so aus:

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

In der obigen Button-Komponente behandeln die Button.css- Stile die allgemeinen Button-Stile. In diesem Beispiel nur eine .buttonKlasse

Dann in meiner Komponente , wo ich will die verwenden Knopf , und ich möchte auch , wie die Position der Schaltfläche Dinge ändern, ich zusätzliche Stile festlegen Promo.cssund durch als classNameStütze. In diesem Beispiel wieder .buttonKlasse genannt. Ich hätte es alles nennen können, z promoButton.

Natürlich wird diese Klasse mit CSS-Modulen sein, .Promo__button___2MVMDwährend die Schaltfläche so etwas wie sein wird.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} );
svnm
quelle
Update 2018: Die Verwendung von propTypes und defaultProps zur Behandlung von Fällen, in denen eine Eigenschaft möglicherweise vorhanden ist oder nicht, ist sauberer und wird bevorzugt.
BrianHVB
6

Verwenden Sie, wie bereits erwähnt, einen interpretierten Ausdruck mit geschweiften Klammern.

Vergessen Sie jedoch nicht, einen Standard festzulegen.
Andere haben vorgeschlagen, eine OR-Anweisung zu verwenden, um eine leere Zeichenfolge zu setzen, wenn undefined.

Aber es wäre noch besser, deine Requisiten zu deklarieren.

Vollständiges Beispiel:

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: '',
};
Jamietelin
quelle
4

Sie können dies erreichen, indem Sie den von der übergeordneten Komponente an die untergeordnete Komponente übergebenen Klassennamen mit "interpolieren" this.props.className. Beispiel unten:

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>
  }
}
Stafie Anatolie
quelle
1

Mit React 16.6.3 und @Material UI 3.5.1 verwende ich Arrays in className wie className={[classes.tableCell, classes.capitalize]}

Versuchen Sie in Ihrem Fall Folgendes.

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

Mit der Unterstützung von React für die Zeichenfolgeninterpolation können Sie Folgendes tun:

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

Tom Goldenberg
quelle
0

In Typescript müssen Sie Typen von HTMLAttributesund festlegen React.FunctionComponent.

In den meisten Fällen müssen Sie es auf eine andere Schnittstelle oder einen anderen Typ erweitern.

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;
}
Rost
quelle