Manera correcta de manejar el estilo condicional en React


93

Estoy haciendo React en este momento y me preguntaba si hay una forma "correcta" de hacer un estilo condicional. En el tutorial que usan

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

Prefiero no usar estilos en línea, por lo que quiero usar una clase para controlar el estilo condicional. ¿Cómo se abordaría esto en la forma de pensar de React? ¿O debería usar esta forma de estilo en línea?


1
Creo que es posible que tenga reduxy reactconfundido. Redux no tiene nada que ver con el estilo.
rossipedia

3
Creo que su preferencia es acertada para los documentos, pero demasiado entusiasta para las aplicaciones donde la compatibilidad de intercambio de marcas no es importante. Algunas aplicaciones web importantes se están deshaciendo de las clases y utilizan solo el estilo en línea, que es más predecible y más fácil de razonar que cuál de las 5 reglas aplicadas hace que el texto esté en negrita. cuando los atributos son dinámicos, no ahorra mucho ancho de banda como lo hace con los documentos repetitivos. La semántica de la aplicación (marcado de origen de vista) tampoco es tan importante ...
dandavis

@rossipedia ah sí, gracias, me confundí, estaba mirando el tutorial de redux cuando pensaba en esto, ¡gracias!
Davidhtien

Si no está seguro de cuál será el valor de la decoración de texto debido a la cascada y solo desea aplicar una línea directa si complete es verdadero, tendrá que crear un objeto de estilo. De esta manera, no lo configura en none accidentalmente cuando era otro valor. const style = {} if (complete) {style ['textDecoration'] = 'line-through'}
Edward

Respuestas:


78

Si prefiere usar un nombre de clase, por supuesto use un nombre de clase.

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

También puede encontrar útil el paquete classnames . Con él, su código se vería así:

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

No hay una forma "correcta" de hacer un estilo condicional. Haz lo que funcione mejor para ti. En lo que a mí respecta, prefiero evitar el estilo en línea y utilizar las clases de la forma que acabamos de describir.

POSTCRIPT [06-AGO-2019]

Si bien sigue siendo cierto que React no tiene opiniones sobre el estilo, en estos días recomendaría una solución CSS-in-JS; a saber, componentes de estilo o emoción . Si eres nuevo en React, apégate a las clases CSS o estilos en línea para empezar. Pero una vez que se sienta cómodo con React, le recomiendo que adopte una de estas bibliotecas. Los uso en todos los proyectos.


Hola, si decidiste usar className como tu método de estilo condicional. Sin el classNames lib. Te aconsejo que uses en undefinedlugar de null. La classNamepropiedad toma como tipo de entrada un String o undefined - type (String | undefined) - ⚡️
0xx

3
@JadRizk, un enfoque aún mejor es no establecer className en absoluto si no tiene un valor válido para establecerlo. const attrs = completed?{className:'text-strike'}:{}luego <li {...attrs}>text to maybe strike</li>(operador de propagación). De esa manera, no establece className en absoluto a menos que tenga un buen valor para asignar. Este es un enfoque importante para configurar algunos estilos en línea en los que no puede saber cuál es el valor actual (porque podría ser establecido por CSS en un archivo que quizás no controle).
LinuxDisciple

@LinuxDisciple si todos los campos se evalúan como falsey, classnamessolo devuelve una cadena vacía. Esto no se verá afectado por ningún CSS.
David

@ DavidL.Walsh Hace 21 horas pensé que la solución de JadRizk era una elección falsa entre nully undefinedque aún resultaría en un classatributo sin valor en el html (es decir, en <p class></p>lugar de <p></p>), así que proporcioné un método que evitaba la configuración classNameen absoluto. Da la casualidad de que me equivoqué con la solución de JadRizk. Para el problema indicado, creo que su solución con el refinamiento de JadRizk es la mejor. Mi sintaxis puede establecer una lista arbitraria de accesorios y sus valores de forma condicional, pero es excesivo establecer un nombre de clase.
LinuxDisciple

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

Consulte el código anterior. Eso hará el truco.


3
Estaba buscando exactamente algo como esto. Estilo en línea condicional, gracias.
Souvik Ghosh

<div style = {{visibilidad: this.state.driverDetails.firstName! == undefined? 'visible': 'oculto'}}> </div>. Pequeño error tipográfico en ==.
vinayak shahdeo

31

Si necesita aplicar condicionalmente estilos en línea (aplicar todo o nada), esta notación también funciona:

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

En caso de que 'someCondition' no se cumpla, pasa un objeto vacío.


2
¿No crea este patrón una diferencia innecesaria? Mi comprensión de la diferencia de DOM es que la stylepropiedad aquí siempre cambiaría, ya que en Javascript. {} != {} Si estoy en lo cierto acerca de la diferencia, tal vez sea mejor usar " undefined" en lugar de " {}"
Dawson B

1
Buena nota. No estoy seguro de esto.
Vlado

8

En primer lugar, estoy de acuerdo con usted por una cuestión de estilo: también (y lo hago) aplicar condicionalmente clases en lugar de estilos en línea. Pero puedes usar la misma técnica:

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

Para conjuntos de estados más complejos, acumule una matriz de clases y aplíquelas:

var classes = [];

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

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

6

en lugar de esto:

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

podría intentar lo siguiente usando cortocircuito:

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

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

bit de información clave del enlace:

El cortocircuito significa que en JavaScript, cuando estamos evaluando una expresión AND (&&), si el primer operando es falso, JavaScript cortocircuitará y ni siquiera verá el segundo operando.

Vale la pena señalar que esto devolvería falso si el primer operando es falso, por lo que podría tener que considerar cómo afectaría esto a su estilo.

Las otras soluciones podrían ser mejores prácticas, pero pensé que valdría la pena compartirlas.


3

Otra forma, usando estilo en línea y el operador de extensión

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

De esa manera, será útil en algunas situaciones en las que desee agregar varias propiedades al mismo tiempo según la condición.


1
Buen enfoque si no desea cambiar un estilo predeterminado
dhilt

2

Me encontré con esta pregunta mientras intentaba responder la misma pregunta. El enfoque de McCrohan con las clases array & join es sólido.

A través de mi experiencia, he estado trabajando con una gran cantidad de código ruby ​​heredado que se está convirtiendo a React y, a medida que construimos los componentes, me encuentro buscando tanto las clases CSS existentes como los estilos en línea.

fragmento de ejemplo dentro de un componente:

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

Una vez más, me encuentro alcanzando el código CSS heredado, "empaquetándolo" con el componente y avanzando.

Entonces, realmente siento que está un poco en el aire en cuanto a qué es "mejor", ya que esa etiqueta variará mucho dependiendo de su proyecto.


No debes combinar classNames con el atributo de estilo, eso es un desastre
Sebastian Voráč

0

La mejor manera de manejar el estilo es usando clases con un conjunto de propiedades css.

ejemplo:

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

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

0

Puedes usar algo como esto.

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

O de lo contrario, puede usar el paquete NPM de nombres de clase para hacer que sea más sencillo trabajar con los props className dinámicos y condicionales (especialmente más que la manipulación de cadenas condicional).

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'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.