Bonne façon de gérer le style conditionnel dans React


94

Je fais un peu de React en ce moment et je me demandais s'il y avait une façon "correcte" de faire du style conditionnel. Dans le tutoriel qu'ils utilisent

style={{
  textDecoration: completed ? 'line-through' : 'none'
}}

Je préfère ne pas utiliser de style en ligne, donc je veux plutôt utiliser une classe pour contrôler le style conditionnel. Comment aborder cela dans la manière de penser React? Ou devrais-je simplement utiliser cette méthode de style en ligne?


1
Je pense que vous pourriez avoir reduxet reactconfus. Redux n'a rien à voir avec le style.
rossipedia

3
Je pense que votre préférence est parfaite pour les documents, mais trop zélée pour les applications où la compatibilité de l'échange de balisage n'est pas importante. certaines applications Web majeures se débarrassent en fait des classes et n'utilisent que le style en ligne, ce qui est plus prévisible et plus facile à raisonner que celle des 5 règles appliquées qui rend le texte en gras. lorsque les attributs sont dynamiques, vous n'économisez pas beaucoup de bande passante comme vous le faites avec des documents répétitifs. la sémantique de l'application (balisage de la vue-source) n'est pas si importante non plus ...
dandavis

@rossipedia ah oui merci, je me suis trompé, je regardais le tutoriel redux en pensant à cela, merci!
davidhtien

Si vous n'êtes pas sûr de la valeur de la décoration de texte à cause de la cascade et que vous ne voulez appliquer une ligne de passage que si complete est vrai, vous devrez créer un objet de style. De cette façon, vous ne le définissez pas accidentellement sur aucun alors qu'il s'agissait d'une autre valeur. const style = {} if (complete) {style ['textDecoration'] = 'line-through'}
Edward

Réponses:


78

Si vous préférez utiliser un nom de classe, utilisez certainement un nom de classe.

className={completed ? 'text-strike' : null}

Vous pouvez également trouver le package classnames utile. Avec lui, votre code ressemblerait à ceci:

className={classNames({ 'text-strike': completed })}

Il n'y a pas de manière «correcte» de faire du style conditionnel. Faites ce qui vous convient le mieux. Pour ma part, je préfère éviter le style en ligne et utiliser des classes de la manière que je viens de décrire.

POSTSCRIPT [06-AOÛ-2019]

S'il reste vrai que React n'a pas d'opinion sur le style, je recommanderais ces jours-ci une solution CSS-in-JS; à savoir les composants stylisés ou l' émotion . Si vous débutez avec React, tenez-vous-en aux classes CSS ou aux styles en ligne pour commencer. Mais une fois que vous êtes à l'aise avec React, je vous recommande d'adopter l'une de ces bibliothèques. Je les utilise dans chaque projet.


Salut, si vous avez décidé d'utiliser className comme méthode de style conditionnel. Sans le classNames lib. Je vous conseille d'utiliser à la undefinedplace de null. La classNamepropriété prend comme type d'entrée un String ou undefined - type (String | undefined) - ⚡️
0xx

3
@JadRizk, une approche encore meilleure consiste à ne pas définir du tout className si vous n'avez pas de valeur valide pour le définir. const attrs = completed?{className:'text-strike'}:{}puis <li {...attrs}>text to maybe strike</li>(opérateur de propagation). De cette façon, vous ne définissez pas du tout className à moins d'avoir une bonne valeur à attribuer. C'est une approche importante pour définir certains styles en ligne où vous ne pouvez pas savoir quelle est la valeur actuelle (car elle pourrait être définie par CSS dans un fichier que vous ne pouvez pas contrôler).
LinuxDisciple

@LinuxDisciple si tous les champs évaluent à falsey, alors classnamesrenvoie simplement une chaîne vide. Cela ne sera affecté par aucun CSS.
David L. Walsh

@ DavidL.Walsh Il y a 21 heures, je pensais que la solution de JadRizk était un faux choix entre nullet undefinedque cela résulterait toujours en un classattribut sans valeur dans le html (c'est- <p class></p>à- dire au lieu de <p></p>), alors j'ai fourni une méthode qui évitait du tout de définir className. Il se trouve que je me suis trompé sur la solution de JadRizk. Pour le problème déclaré, je pense que votre solution avec le raffinement de JadRizk est la meilleure. Ma syntaxe peut définir une liste arbitraire d'accessoires et leurs valeurs de manière conditionnelle, mais c'est excessif pour simplement définir un nom de classe.
LinuxDisciple

106
 <div style={{ visibility: this.state.driverDetails.firstName != undefined? 'visible': 'hidden'}}></div>

Vérifiez le code ci-dessus. Cela fera l'affaire.


3
Je cherchais exactement quelque chose comme ça. Style en ligne conditionnel, merci.
Souvik Ghosh

<div style = {{visibilité: this.state.driverDetails.firstName! == indéfini? 'visible': 'hidden'}}> </div>. Petite faute de frappe dans ==.
vinayak shahdeo le

31

Si vous devez appliquer conditionnellement des styles en ligne (appliquer tout ou rien), cette notation fonctionne également:

style={ someCondition ? { textAlign:'center', paddingTop: '50%'} : {}}

Si 'someCondition' n'est pas remplie, vous passez un objet vide.


2
Ce modèle ne crée-t-il pas une différence inutile? Ma compréhension de la différence DOM est que l' styleaccessoire ici changerait toujours car en Javascript {} != {} Si j'ai raison à propos de la différence, il est peut-être préférable d'utiliser " undefined" au lieu de " {}"
Dawson B

1
Bonne note. Je ne suis pas certain de cela.
Vlado

8

Premièrement, je suis d'accord avec vous pour une question de style - j'appliquerais également (et ferais aussi) des classes conditionnelles plutôt que des styles en ligne. Mais vous pouvez utiliser la même technique:

<div className={{completed ? "completed" : ""}}></div>

Pour des ensembles d'états plus complexes, accumulez un tableau de classes et appliquez-les:

var classes = [];

if (completed) classes.push("completed");
if (foo) classes.push("foo");
if (someComplicatedCondition) classes.push("bar");

return <div className={{classes.join(" ")}}></div>;

6

au lieu de cela:

style={{
  textDecoration: completed ? 'line-through' : 'none'
}}

vous pouvez essayer ce qui suit en utilisant un court-circuit:

style={{
  textDecoration: completed && 'line-through'
}}

https://codeburst.io/javascript-short-circuit-conditionals-bbc13ac3e9eb

information clé du lien:

Le court-circuit signifie qu'en JavaScript, lorsque nous évaluons une expression AND (&&), si le premier opérande est faux, JavaScript court-circuitera et ne regardera même pas le deuxième opérande.

Il est intéressant de noter que cela renverrait false si le premier opérande est faux, vous devrez peut-être considérer comment cela affecterait votre style.

Les autres solutions sont peut-être plus de bonnes pratiques, mais elles ont estimé qu'elles mériteraient d'être partagées.


3

Une autre façon, en utilisant le style en ligne et l'opérateur de propagation

style={{
  ...completed ? { textDecoration: completed } : {}
}}

Cela peut être utile dans certaines situations où vous souhaitez ajouter un ensemble de propriétés en même temps en fonction de la condition.


1
Bonne approche si vous ne voulez pas changer un style par défaut
dhilt

2

Je suis tombé sur cette question en essayant de répondre à la même question. L'approche de McCrohan avec le tableau et la jointure des classes est solide.

Grâce à mon expérience, j'ai travaillé avec beaucoup de code ruby ​​hérité qui est converti en React et à mesure que nous construisons le (s) composant (s), je me retrouve à la recherche de classes css existantes et de styles en ligne.

exemple d'extrait de code à l'intérieur d'un composant:

// if failed, progress bar is red, otherwise green 
<div
    className={`progress-bar ${failed ? failed' : ''}`}
    style={{ width: this.getPercentage() }} 
/>

Encore une fois, je me trouve en train de tendre la main au code css hérité, de le «conditionner» avec le composant et de passer à autre chose.

Donc, j'ai vraiment l'impression qu'il y a un peu de doute sur ce qui est «meilleur» car ce label variera énormément en fonction de votre projet.


Vous ne devriez pas combiner classNames avec l'attribut style, c'est un peu le bordel
Sebastian Voráč

0

La meilleure façon de gérer le style consiste à utiliser des classes avec un ensemble de propriétés css.

exemple:

<Component className={this.getColor()} />

getColor() {
    let class = "badge m2";
    class += this.state.count===0 ? "warning" : danger;
    return class;
}

0

Vous pouvez utiliser quelque chose comme ça.

render () {
    var btnClass = 'btn';
    if (this.state.isPressed) btnClass += ' btn-pressed';
    else if (this.state.isHovered) btnClass += ' btn-over';
    return <button className={btnClass}>{this.props.label}</button>;
  }

Ou bien, vous pouvez utiliser le package NPM de noms de classe pour simplifier le travail des accessoires de nom de classe dynamiques et conditionnels (en particulier plus que la manipulation de chaînes conditionnelles).

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'
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.