Maneira correta de lidar com o estilo condicional no React


102

Estou fazendo um React agora e queria saber se existe uma maneira "correta" de fazer estilo condicional. No tutorial, eles usam

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

Prefiro não usar estilo embutido, então quero usar uma classe para controlar o estilo condicional. Como alguém abordaria isso no modo de pensar React? Ou devo apenas usar essa forma de estilo embutido?


1
Eu acho que você pode ter reduxe reactconfundido. Redux não tem nada a ver com estilo.
rossipedia

3
Acho que sua preferência é exata para documentos, mas zeloso demais para aplicativos em que a compatibilidade de intercâmbio de marcação não é importante. alguns dos principais aplicativos da web estão realmente se livrando das classes e usando apenas o estilo embutido, que é mais previsível e mais fácil de raciocinar do que qual das 5 regras aplicadas está deixando o texto em negrito. quando os atributos são dinâmicos, você não economiza muita largura de banda como faz com documentos repetitivos. a semântica do aplicativo (marcação de fonte de visualização) também não é tão importante ...
dandavis

@rossipedia ah sim obrigado, confundi, tava olhando o tutorial de redux quando pensava nisso, obrigado!
davidhtien

Se você não tiver certeza de qual será o valor de text-decoration por causa da cascata e só quiser aplicar uma linha se complete for true, você terá que construir um objeto de estilo. Dessa forma, você não o define como nenhum acidentalmente quando era outro valor. const style = {} if (complete) {style ['textDecoration'] = 'line-through'}
Edward

Respostas:


80

Se você preferir usar um nome de classe, use um nome de classe.

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

Você também pode achar o pacote de nomes de classe útil. Com ele, seu código ficaria assim:

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

Não há uma maneira "correta" de definir estilos condicionais. Faça o que funcionar melhor para você. Para mim, prefiro evitar estilos embutidos e usar classes da maneira que acabei de descrever.

POSTSCRIPT [06-AGO-2019]

Embora seja verdade que o React não tem opinião sobre estilos, atualmente eu recomendaria uma solução CSS-in-JS; ou seja , componentes de estilo ou emoção . Se você é novo no React, use as classes CSS ou estilos embutidos para começar. Mas quando você estiver confortável com o React, recomendo adotar uma dessas bibliotecas. Eu os uso em todos os projetos.


Olá, se você decidiu usar className como seu método de estilo condicional. Sem o classNames lib. Aconselho você a usar em undefinedvez de null. A classNamepropriedade toma como tipo de entrada uma String ou undefined - type (String | undefined) - ⚡️
0xx

4
A abordagem ainda melhor do @JadRizk é não definir className se você não tiver um valor válido para defini-lo. const attrs = completed?{className:'text-strike'}:{}então <li {...attrs}>text to maybe strike</li>(operador spread). Dessa forma, você não define className, a menos que tenha um bom valor para atribuir. Esta é uma abordagem importante para definir alguns estilos embutidos em que você não pode saber qual é o valor atual (porque ele pode ser definido por CSS em um arquivo que você não pode controlar).
LinuxDisciple

@LinuxDisciple se todos os campos forem avaliados como falsey, então classnamesapenas retornará uma string vazia. Isso não será afetado por nenhum CSS.
David L. Walsh

@ DavidL.Walsh 21 horas atrás eu pensei que a solução de JadRizk era uma falsa escolha entre nulle undefinedisso ainda resultaria em um classatributo sem valor no html (isto é, em <p class></p>vez de <p></p>), então eu forneci um método que evitou a configuração className. Acontece que eu estava errado sobre a solução do JadRizk. Para o problema declarado, acredito que sua solução com o refinamento de JadRizk seja a melhor. Minha sintaxe pode definir uma lista arbitrária de adereços e seus valores condicionalmente, mas é um exagero apenas definir um nome de classe.
LinuxDisciple

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

Verifique o código acima. Isso será o suficiente.


4
Estava exatamente procurando por algo assim. Estilo embutido condicional, obrigado.
Souvik Ghosh

<div style = {{visibility: this.state.driverDetails.firstName! == undefined? 'visible': 'hidden'}}> </div>. Pequeno erro de digitação em ==.
vinayak shahdeo

39

Se você precisar aplicar condicionalmente estilos embutidos (aplicar tudo ou nada), esta notação também funciona:

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

Caso 'algumaCondição' não seja cumprida, você passa o objeto vazio.


2
Este padrão não cria uma diferença desnecessária? Meu entendimento de diffing DOM é que o styleprop aqui sempre mudaria desde em Javascript. {} != {} Se eu estiver correto sobre o diffing, talvez seja melhor usar " undefined" em vez de " {}"
Dawson B

1
Boa nota. Eu não tenho certeza sobre isso.
Vlado

8

Primeiro, concordo com você em uma questão de estilo - eu também (e também) aplicaria classes condicionalmente em vez de estilos embutidos. Mas você pode usar a mesma técnica:

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

Para conjuntos de estados mais complexos, acumule uma série de classes e aplique-as:

var classes = [];

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

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

8

em vez disso:

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

você pode tentar o seguinte usando curto-circuito:

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

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

informação importante do link:

Curto-circuito significa que no JavaScript, quando estamos avaliando uma expressão AND (&&), se o primeiro operando for falso, o JavaScript entrará em curto-circuito e nem mesmo olhará para o segundo operando.

É importante notar que isso retornaria falso se o primeiro operando fosse falso, então você deve considerar como isso afetaria seu estilo.

As outras soluções podem ser mais práticas recomendadas, mas pensei que valeria a pena compartilhar.


4

Outra forma, usando o estilo inline e o operador spread

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

Isso pode ser útil em algumas situações em que você deseja adicionar várias propriedades ao mesmo tempo com base na condição.


1
Boa abordagem se você não quiser alterar um estilo padrão
dhilt

2

Eu me deparei com essa pergunta ao tentar responder à mesma pergunta. A abordagem de McCrohan com as classes array & join é sólida.

Por meio da minha experiência, tenho trabalhado com muito código Ruby legado que está sendo convertido para React e, à medida que construímos o (s) componente (s), encontro-me buscando classes css existentes e estilos inline.

snippet de exemplo dentro de um componente:

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

Novamente, encontro-me buscando o código CSS legado, "empacotando"-o com o componente e seguindo em frente.

Então, eu realmente sinto que está um pouco no ar sobre o que é "melhor", já que esse rótulo pode variar muito dependendo do seu projeto.


Você não deve combinar classNames com atributo de estilo, isso é uma bagunça
Sebastian Voráč

0

A melhor maneira de lidar com o estilo é usando classes com um conjunto de propriedades css.

exemplo:

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

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

0

Você pode usar algo assim.

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 então, você pode usar o pacote NPM de classnames para tornar os props className dinâmicos e condicionais mais simples de trabalhar (especialmente mais do que a manipulação de string 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'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.