CSS

26 abr, 2017

Componentes stateless com styles stateless

Publicidade

Muito tem sido dito sobre os componentes stateless e imutabilidade, mas tem algo de que as pessoas estão se esquecendo: manter os estilos dos seus componentes stateless.

O negócio com os componentes – e os stateless – é que você desenvolve algo para ser utilizado em qualquer ponto com pouco esforço para implementá-los. Mas eu vi muitos projetos, incluindo alguns open source, que estão se importando com como e onde seus componentes serão utilizados, e isso é errado – essa responsabilidade pertence ao aplicativo que os estiver implementando.

Digamos que você tem um componente input com alguma funcionalidade específica. Você pode dizer que tem um preenchimento de 3 px, mas configurar sua width o torna “stateful” porque você está considerando que o mundo externo será capaz de renderizá-lo perfeitamente, o que frequentemente não ocorre.

Você configura o min-width (largura mínima) de uma saída para ser 100px, mas acontece de você precisar colocar ela em um widget que tenha 75px de largura – como você vai proceder?

Talvez removendo a propriedade min-width, mas a precaução é um requisito aqui, pois algum outro ponto pode exigir que essa propriedade seja 100px para que exista uma aparência e sentimentos corretos. Então quebra. Pensando nisso, esse é um efeito de ter um stateful thing, o que é mais difícil de acontecer quando se trata de componentes stateless.

O ponto chave aqui é: o espaço físico onde seu componente será alocado é um problema que seu container deve determinar, e mais ninguém. É ele quem conhece seu território e quanto de espaço tem disponível para permitir que uma coisa seja renderizada sem quebrar a experiência visual.

Um exemplo sólido

Vou utilizar um Lightbox para demonstrar meu raciocínio. Naturalmente, ele exige um espaço absoluto. E um espaço absoluto é… absoluto. Ele ignora o que está por trás e se posiciona à frente de tudo. Mas eu sugiro que você mantenha os styles stateless, porque um dia você pode querer esse mesmo componente em outro lugar que não seja uma janela de exibição completa – aconteceu comigo uma vez –, e você terá alguma dor de cabeça se criá-la para pertencer exclusivamente a uma janela de exibição.

Mas com eu consigo um Lightbox stateless?

Normalmente utilizamos soluções assim:

<Lightbox>
  <img
    className={styles.lightbox__image}
    src="http://some.image.com"
  />
</Lightbox>

Quanto aos styles:

.lightbox {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
}

.lightbox__image {
  max-width: 960px;
  height: 100%;
  background-color: #000; // until the image is loaded.
}

Mas isso é perigoso. Você está tentando prever como e onde seu Lightbox será utilizado. Um Lightbox stateless seria assim:

<div
  style={{
    position: 'fixed',
    top: 0,
    left: 0,
    width: 100vw;
    height: 100vh;
  }}
>
  <Lightbox>
    <img
      className={styles.lightbox__image}
      src="http://some.image.com"
    />
  </Lightbox>
</div>

E para os Lightbox´s styles:

.lightbox {}

.lightbox__image {
  max-width: 80%;
  height: 100%;
  background-color: #000; // until the image is loaded.
}

Dessa maneira, seu componente abandona toda sua compreensão sobre o espaço físico assim como sua complexidade, o que significa que você pode movê-lo agora para qualquer ponto que você queira e sua experiência será tranquila. É ridículo – ele não se importa com onde será posicionado, mas será responsivo o suficiente para se ajustar para sua nova posição.

Além disso, sua aplicação poderá ter um componente chamado widget que seja um container em branco que apresentará alguma coisa com um título. Algo assim:

<Widget
  title="Read all blog posts"
  onClickCallToAction={this.redirectToBlogPosts}
/>

<Widget
  title="Read all comments"
  onClickCallToAction={this.redirectToPostComments}
/>

A princípio, você pode imaginar que você vai utilizá-lo somente em containers específicos. Mas conforme sua aplicação cresça e você queira manter seu design consistente, você vai querer reutilizar o que tem. E você vai conseguir fazer isso mais facilmente assim que seus componentes e seus estilos estiverem stateless.

Em vez de criar esses Widgets prevendo suas dimensões, uma coisa da qual somente o container tem conhecimento, nós podemos melhorar assim:

<main style={{width: 300}}>
  <Widget
    title="Read all blog posts"
    onClickCallToAction={this.redirectToBlogPosts}
  />
</main>

<aside style={{width: 200}}>
  <Widget
    title="Read all comments"
    onClickCallToAction={this.redirectToPostComments}
  />
</aside>

E o estilo do Widget poderia ter largura de 100%. Ou 80%. Ou qualquer outra. Ele não sabe sobre o container, somente sobre o estilo. “Se o container tiver 100px, então minha largura será 100px, ou 80px. E funcionará como esperado”.

E os componentes que precisam de um espaço mínimo para que funcionem conforme o esperado?

Se você posicionar seu componente dentro de um container de 1px, provavelmente não funcionará. Sim, às vezes seu componente vai precisar de um espaço mínimo para se manifestar. E, nessa circunstância, como podemos proceder?

O ponto é a mindset.

O seu componente precisa de um mínimo de 100px para se comportar de maneira apropriada. Se você precisar apresentá-lo dentro de um container de 80px de largura, então:

  • Você poderá precisar refatorar seu estilos;
  • Você poderá repensar se esse lugar é o ideal para o design.

Marcar a largura mínima que um componente precisa para funcionar consiste basicamente na propriedade min-width. Você a configura e, então, ela automaticamente determina quanto de espaço você vai precisar, no mínimo. Ela não expressa o tamanho exato – porque isso não importa –, mas sua flexibilidade.

Ah… Estou trabalhando em uma barra lateral reutilizável que tem um limite de 300px. E agora?

Max-width (largura máxima) será sua solução, como o min-width foi para o espaço mínimo a ser ocupado.

Ok… mas isso é realmente seguro?

Sim. Vai quebrar quando o espaço para trabalho não estiver explicitamente configurado. Caso contrário, será flexível e seguro.

Mas eu tenho um componente reutilizável que requer uma largura/ altura exata!

Certamente. Eu também. Então você pode configurar sua largura para ser exatamente a que você quer. Se você está confiante que essa não será uma circunstância em que você vai querer em um espaço diferente, faça! Este artigo é a opinião pessoal que alimentou um processo mais rápido e mais flexível de correção, com uma saída de código menos propenso a erros.

***

Guilherme Oderdenge faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://medium.com/@chiefgui/stateless-components-with-stateless-styles-9a592f8fcab0.