Como deixar componentes React mais organizados mesmo com Tailwind CSS?!
Tags: react, tailwindcss, css, vanillaextract
Published: 2023-04-04 15:48:41

## Contexto
Muito se discute sobre as melhores formas de escrever CSS usando React. Por existirem diversas possibilidades (frameworks diferentes, CSS-in-JS, SASS, ...) as opiniões costumam ser divergentes.
Após a recente atualização na documentação do React, o Next.js (Next.js é um framework React full-stack) passou a ser indicado como uma das principais maneiras de se iniciar um projeto React.

Seguindo a própria [documentação do Next.js](https://beta.nextjs.org/docs/styling/tailwind-css), podemos ver que o Tailwind é uma ótima opção para ser utilizada para estilização:

> Tailwind CSS is a utility-first CSS framework that works exceptionally well with Next.js.


As maiores críticas que costumo ver ao Tailwind são:

- Deixa o HTML "sujo";
- Não pode ser reaproveitado, gerando muita repetição de código.


![Homem falando "Blah blah blah"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7m4xm6nunaznnjc1gz2f.png)

## Conteúdo
Após estudar um pouco sobre CSS Modules e [Vanilla Extract](https://vanilla-extract.style/), percebi que podemos utilizar a "mesma ideia" de organização para tornar o Tailwind mais agradável e manutenível.

Para isso, vou usar de exemplo a refatoração de um pequeno componente de uma Navbar.


![Badge escrito "Don't"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eh73vjlysede0akz4ix0.png)
```JSX
function NavbarUnorganized () {
  return (
    <nav className="flex flex-col lg:flex-row lg:px-48 gap-8 lg:gap-0  py-5 border-b-2 border-green-600 items-center justify-between bg-backgroundWhite">
      <a href="/">
        <img className="w-[125px]" src="#" alt="Logo da Nav de Exemplo." />
      </a>
      <ul className="flex flex-col md:flex-row gap-2 md:gap-8 font-kalam">
          <li><a href="/" className='text-green-600 text-xl lg:text-2xl navlink'>Home</a></li>
          <li><a href="/produtos" className='text-green-600 text-xl lg:text-2xl navlink'>Produtos</a></li>
          <li><a href="/contato" className='text-green-600 text-xl lg:text-2xl navlink'>Contato</a></li>
          <li><a href="/carrinho" className="flex items-center gap-2 text-green-600 text-xl lg:text-2xl navlink">Carrinho</a></li>
      </ul>
    </nav>
  );
}
```

Nesse caso, temos um componente simples, sem lógica associada. Mesmo assim podemos perceber a dificuldade de dar manutenção em um código assim. Se precisarmos alterar os estilos da lista, teríamos que ir em item por item.


![Badge escrito "Do"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a5reu677tf1wrbliqimh.png)

Podemos melhorar isso simplesmente criando um arquivo JS para armazenar os estilos em variáveis:
```JS
//index.css.js
export const container = "flex flex-col lg:flex-row lg:px-48 gap-8 lg:gap-0  py-5 border-b-2 border-fontPurple items-center justify-between bg-backgroundWhite"

export const ul = "flex flex-col md:flex-row gap-2 md:gap-8 font-kalam"

export const navLink = "text-green-600 text-xl lg:text-2xl navlink"
```

Agora podemos importar essas variáveis em nosso componente e utilizá-la em nossas classes, tornando-o bem mais legível:

```JSX
//index.jsx
import {
	container,
	ul,
	navLink } from "./index.css";

function NavbarOrganized () {
    return (
        <nav className={container}>
          <a href="/">
            <img className="w-[125px]" src={'https://http.cat/202'} alt="Logo da Nav de Exemplo." />
          </a>
          <ul className={ul}>
              <li><a href="/" className={navLink}>Home</a></li>
              <li><a href="/produtos" className={navLink}>Produtos</a></li>
              <li><a href="/contato" className={navLink}>Contato</a></li>
              <li><a href="/carrinho" className={navLink}>Carrinho</a></li>
          </ul>
        </nav>
      )
}
```

# Dica extra
![Placa escrito "Bônus"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0ec4lt1488lyrl8tehi.png)
Pelo fato do nosso index.css.js ser um arquivo Javascript, podemos também utilizar interpolações para extrair padrões de texto (conjunto de classes). Por exemplo com padrões que se repetem com frequência como flex-containers, poderíamos passar disso:

```js
export const container = "flex flex-col items-center justify-between lg:flex-row lg:px-48 gap-8 lg:gap-0  py-5 border-b-2  bg-backgroundWhite"

export const ul = "flex flex-col items-center justify-between md:flex-row gap-2 md:gap-8 font-kalam"

export const navLink = "text-green-600 text-xl lg:text-2xl navlink"
```
Para algo mais simples:
```js
const flexCol = "flex flex-col items-center justify-between" 

export const container = `${flexCol}  lg:flex-row lg:px-48 gap-8 lg:gap-0  py-5 border-b-2  bg-backgroundWhite`

export const ul = `${flexCol} md:flex-row gap-2 md:gap-8 font-kalam`

export const navLink = "text-green-600 text-xl lg:text-2xl navlink"
```
Como esse tipo de padrão se repete muito ao longo de um projeto, talvez você queira armazenar esses conjuntos de classes em um arquivo global, fora do componentes.

## Conclusão
Existem diversas maneiras de tornar o uso do Tailwind mais simples e de aproveitar o reuso dos estilos.
Alguns recursos são nativos e estão na própria [documentação](https://tailwindcss.com/docs/reusing-styles) (como a extração de classes com o uso do `@apply`, criação de um componente, uso de loops, etc).

Mas atualmente tenho gostado bastante de extrair como string (em vez de usar `@apply`), pois é mais rápido/prático.