React Js appliquant conditionnellement des attributs de classe

334

Je veux afficher et masquer ce groupe de boutons de manière conditionnelle en fonction de ce qui est passé du composant parent qui ressemble à ceci:

<TopicNav showBulkActions={this.__hasMultipleSelected} />

....

__hasMultipleSelected: function() {
  return false; //return true or false depending on data
}

....

var TopicNav = React.createClass({
render: function() {
return (
    <div className="row">
        <div className="col-lg-6">
            <div className="btn-group pull-right {this.props.showBulkActions ? 'show' : 'hidden'}">
                <button type="button" className="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
                  Bulk Actions <span className="caret"></span>
                </button>
                <ul className="dropdown-menu" role="menu">
                  <li><a href="#">Merge into New Session</a></li>
                  <li><a href="#">Add to Existing Session</a></li>
                  <li className="divider"></li>
                  <li><a href="#">Delete</a></li>
                </ul>
            </div>
        </div>
    </div>
    );
  }
});

Cependant, rien ne se passe avec les {this.props.showBulkActions? 'show': 'caché'}. Suis-je en train de faire quelque chose de mal ici?

apexdodge
la source
Vous pouvez également envisager de réagir-bootstrap , car cela résume certains éléments de la classe dans les propriétés des composants, ce qui rend ce que vous essayez de faire un peu plus facile.
Dancrumb

Réponses:

591

Les accolades sont à l'intérieur de la chaîne, elle est donc évaluée en tant que chaîne. Ils doivent être à l'extérieur, donc cela devrait fonctionner:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? 'show' : 'hidden')}>

Notez l'espace après "tirer vers la droite". Vous ne voulez pas fournir accidentellement la classe "pull-rightshow" au lieu de "pull-right show". Les parenthèses doivent également être présentes.

spitfire109
la source
3
Merci! J'ai dû le modifier légèrement parce que pour une raison quelconque, il ne produisait pas du tout le droit d'extraction du groupe btn. Afficher ou masquer.
apexdodge
Cela est particulièrement utile dans certains cas où cela classnamespourrait ne pas être approprié. Si vous êtes dans votre renderfonction et que vous en avez un map, vous ne savez peut-être que si vous voulez ajouter une classe au moment où vous la rendez, donc cette réponse est très utile pour cela.
Dave Cooper
excellente alternative au lieu d'avoir un tas de modèles conditionnels dans votre rendu ou retour
devonj
@apexdodge quelle modification vous avez dû faire. J'ai le même problème.
RamY
1
@RamY Une façon consiste à mettre toutes les classes à l'intérieur du conditionnel this.props.showBulkActions ? 'btn-group pull-right show' : 'btn-group pull-right hidden'). Pas élégant mais ça marche.
Ian
87

Comme d'autres l'ont commenté, les noms de classe utilitaire est l'approche actuellement recommandée pour gérer les noms de classe CSS conditionnels dans ReactJs.

Dans votre cas, la solution ressemblera à:

var btnGroupClasses = classNames(
  'btn-group',
  'pull-right',
  {
    'show': this.props.showBulkActions,
    'hidden': !this.props.showBulkActions
  }
);

...

<div className={btnGroupClasses}>...</div>

En guise de remarque, je vous suggère d'essayer d'éviter d'utiliser à la fois les classes showet hidden, afin que le code puisse être plus simple. Vous n'avez probablement pas besoin de définir une classe pour que quelque chose soit affiché par défaut.

Diego V
la source
11
Pourriez-vous préciser que l'utilitaire classNames est "l'approche actuellement recommandée"? Cela figure-t-il quelque part dans un document de bonnes pratiques bien considéré? Ou tout simplement le bouche à oreille autour de React et classNamesen ce moment?
Alexander Nied
6
@anied Au moment de la rédaction, il était recommandé dans la documentation officielle de React: web.archive.org/web/20160602124910/http://facebook.github.io:80/…
Diego V
3
Il est toujours mentionné dans la dernière documentation : " Si vous vous retrouvez souvent à écrire du code comme celui-ci, le package des noms de classe peut le simplifier. "
Franklin Yu
66

Si vous utilisez un transpilateur (comme Babel ou Traceur), vous pouvez utiliser les nouvelles " chaînes de modèle " ES6 .

Voici la réponse de @ spitfire109, modifiée en conséquence:

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'shown' : 'hidden'}`}>

Cette approche vous permet de faire des choses intéressantes comme ça, en rendant soit s-is-shownou s-is-hidden:

<div className={`s-${this.props.showBulkActions ? 'is-shown' : 'is-hidden'}`}>
Bertrand
la source
20
Soyez prudent avec la deuxième approche, en particulier dans les grandes bases de code, car elle rend les chaînes de classe moins acceptables. Par exemple, si quelqu'un recherche s-is-shownou s-is-hiddendans la base de code, il ne trouvera pas ce code.
marquer
15

Vous pouvez utiliser ici des littéraux de chaîne

const Angle = ({show}) => {

   const angle = `fa ${show ? 'fa-angle-down' : 'fa-angle-right'}`;

   return <i className={angle} />
}
Musa
la source
9

En dépensant sur la bonne réponse de @ spitfire109, on pourrait faire quelque chose comme ceci:

rootClassNames() {
  let names = ['my-default-class'];
  if (this.props.disabled) names.push('text-muted', 'other-class');

  return names.join(' ');
}

puis dans la fonction de rendu:

<div className={this.rootClassNames()}></div>

garde le jsx court

floconneux
la source
8

Ou utilisez des noms de classe npm . C'est très simple et utile surtout pour construire la liste des classes

Vérification au crayon
la source
8

Dans le cas où vous aurez besoin d'un seul nom de classe facultatif:

<div className={"btn-group pull-right " + (this.props.showBulkActions ? "show" : "")}>
Eugene Chybisov
la source
1
Cela ajoutera la falseclasse lorsque la condition échoue.
RA.
6

Vous pouvez utiliser des tableaux ES6 au lieu de noms de classe. La réponse est basée sur l'article du Dr. Axel Rauschmayer: Ajout conditionnel d'entrées à l'intérieur de tableaux et d'objets littéraux .

<div className={[
                 "classAlwaysPresent", 
                 ...Array.from(condition && ["classIfTrue"])
                ].join(" ")} />
Tudor Morar
la source
veuillez développer ceci, quelle est la condition?
mibbit
condition const = (1 === 1);
Tudor Morar
5

2019:

React est un lac de nombreux services publics. Mais vous n'avez besoin d'aucun npmpackage pour cela. créez quelque part la fonction classnameset appelez-la quand vous en avez besoin;

function classnames(obj){
  return Object.entries(obj).filter( e => e[1] ).map( e=>e[0] ).join(' ');
}

ou

function classnames(obj){
 return Object.entries(obj).map( ([k,v]) => v?k:'' ).join(' ');
}

exemple

  stateClass= {
    foo:true,
    bar:false,
    pony:2
  }
  classnames(stateClass) // return 'foo pony'

 <div className="foo bar {classnames(stateClass)}"> some content </div>

Juste pour l'inspiration

déclarer l'élément d'assistance et utilisé la toggleméthode

(DOMToken​List)classList.toggle(class,condition)

exemple:

const classes = document.createElement('span').classList; 

function classstate(obj){
  for( let n in obj) classes.toggle(n,obj[n]);
 return classes; 
}
pery mimon
la source
4

Solution plus élégante, meilleure pour la maintenance et la lisibilité:

const classNames = ['js-btn-connect'];

if (isSelected) { classNames.push('is-selected'); }

<Element className={classNames.join(' ')}/>
Nate Ben
la source
3

vous pouvez utiliser ceci:

<div className={"btn-group pull-right" + (this.props.showBulkActions ? ' show' : ' hidden')}>
AmirBll
la source
2

Cela fonctionnerait pour vous

var TopicNav = React.createClass({
render: function() {

let _myClasses = `btn-group pull-right {this.props.showBulkActions?'show':'hidden'}`;

return (
            ...
            <div className={_myClasses}>
               ...
            </div>
    );
  }
});
Manoj Amalraj
la source
1

Vous pouvez utiliser ce package npm. Il gère tout et dispose d'options pour les classes statiques et dynamiques basées sur une variable ou une fonction.

// Support for string arguments
getClassNames('class1', 'class2');

// support for Object
getClassNames({class1: true, class2 : false});

// support for all type of data
getClassNames('class1', 'class2', null, undefined, 3, ['class3', 'class4'], { 
    class5 : function() { return false; },
    class6 : function() { return true; }
});

<div className={getClassNames('show', {class1: true, class2 : false})} /> // "show class1"
Tushar Sharma
la source
1

En fonction de la valeur de this.props.showBulkActionsvous pouvez changer de classe dynamiquement comme suit.

<div ...{...this.props.showBulkActions 
? { className: 'btn-group pull-right show' } 
: { className: 'btn-group pull-right hidden' }}>
Vladimir Trifonov
la source
1

Je voudrais ajouter que vous pouvez également utiliser un contenu variable dans le cadre de la classe

<img src={src} alt="Avatar" className={"img-" + messages[key].sender} />

Le contexte est un chat entre un bot et un utilisateur, et les styles changent en fonction de l'expéditeur, voici le résultat du navigateur:

<img src="http://imageurl" alt="Avatar" class="img-bot">
JC
la source
1

Ceci est utile lorsque vous avez plusieurs classes à ajouter. Vous pouvez joindre toutes les classes dans un tableau avec un espace.

const visibility = this.props.showBulkActions ? "show" : ""
<div className={["btn-group pull-right", visibility].join(' ')}>
kooskoos
la source
1

Remplacer:

<div className="btn-group pull-right {this.props.showBulkActions ? 'show' : 'hidden'}">`

avec:

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}
Amit Agarwal
la source
0

Référence à @split fire answer, nous pouvons le mettre à jour avec des littéraux de modèle, ce qui est plus lisible, pour référence Checkout javascript template literal

<div className={`btn-group pull-right ${this.props.showBulkActions ? 'show' : 'hidden'}`}>
Akhil Aravind
la source
0

J'ai trouvé cela qui explique comment le faire avec un ternaire et avec la bibliothèque de noms de classes

chachan
la source