Composition Pattern

Mastering React Composition

Você já está utilizando o Composition Pattern em seus projetos? Se não, deveria. Vou explicar um pouco o motivo neste post.

Antigamente, costumávamos usar props para gerenciar componentes, tanto visualmente quanto na lógica de implementação em si.

Um cenário comum que nos deparamos é construir um campo de input como vemos logo abaixo:

inputexemplo de como geralmente são com múltiplas props


Nesse modelo, ficamos presos a uma implementação confusa e à necessidade de adicionar e manter uma infinidade de possíveis mudanças de layout ou estilo do componente. Sempre é necessário criar uma nova prop ou até mesmo “slots” para adicionar uma nova camada de visualização em nosso componente.

Bom, como podemos melhorar a implementação desse componente e torná-lo mais amigável para nós, desenvolvedores?

O primeiro passo é quebrar esse componente em partes menores. O padrão de composição envolve a construção de componentes complexos combinando componentes menores, chamados de componentes de baixo nível ou componentes primitivos.

estrutura de um componenteestrutura de um componente

Nessa estrutura de pasta, podemos ver que o componente foi dividido em várias camadas, cada uma isolando a responsabilidade do que o nome do arquivo indica. Ao separar um componente em várias partes, temos um controle maior tanto da visualização quanto da implementação, sem precisar lidar com vários estados em um mesmo arquivo ou testar todas as infinitas variações de propriedades (um peso para os desenvolvedores).

Pulamos, então, de um conceito de “N props” para uma composição mais eficiente. A maior vantagem desse modelo de criação é a capacidade de decidir o que você precisa no momento, sem adicionar lógica adicional de organização dos elementos. Veja o exemplo abaixo:

exemplo de uso de um pós refatoraçãoexemplo de uso de um pós refatoração

A maior vantagem desse modelo de criação é realmente a decisão de o que você precisa nesse momento ou não (além claro da manutenção e construção), como por exemplo, um input sem o componente de Label basta não renderizar o componente Input.Label

<Input.Root>
  <Input.Group>
    <Input.Icon icon={<User color="#999" size={18} />} /> 
    <Input.Input
      placeholder="Seu nome de usuário"
      type="text" {...register("username", { required:true })} 
    />
  </Input.Group>
</Input.Root>

Abaixo um exemplo de que podemos fazer um implementação um pouco mais complexa adicionando apenas um novo Icon a direita do Input sem ter que adicionar nada de lógica de organização dos elementos.

adicionando ícones a este componenteadicionando ícones a este componente

Resumindo, ao seguir esse padrão, temos:

  • Componentes mais claros de entender;

  • Manutenção mais focada;

  • Reutilização, evitando duplicação de componentes e lógicas;

  • Flexibilidade na hora de renderizar um novo componente;

  • Abstração de estados dentro do próprio caso, sem arquivos enormes com infinitas booleanas para controlar a visualização.

E por aí vai…

O que te contei é um pouco do que aprendi, e com certeza posso ter esquecido de algo. Fique à vontade para conversar comigo sobre isso ou sugerir mudanças!

Até breve.

reactpatterns