React: Component PATTERN que você precisa conhecer
Você já viu a lib Headless UI? É uma lib que dispobibiliza componentes como dialog (modal), listbox (select) não estilizados e com acessibilidade. Mas esse post NÃO é sobre isso. Uma coisa muito interessante sobre essa lib (e não é a única que usa esse pattern, muito pelo contrário), é a forma como são os seus componentes são usados:
...
<Dialog>
<Dialog.Panel>
<Dialog.Title>
...
</Dialog.Title>
<Dialog.Description>
...
</Dialog.Description>
...
</Dialog.Panel>
</Dialog>
...
Se você usar só o <Dialog>
ele é como um componente, mas se você usar o <Dialog.Panel>
ele é um outro componente completamente diferente, assim como seu <Dialog.Title>
e <Dialog.Description>
.
Então a questão é, como você pode usar esse pattern para seus próprios componentes?
Como usar esse PATTERN?
Pensando em um exemplo mais prático de aplicar, vamos de uma lista, que é composta de <ul>
e <li>
, o resultado que queremos alcançar é o componente para ser usado da seguinte forma:
<List>
<List.Item>...</List.Item>
<List.Item>...</List.Item>
<List.Item>...</List.Item>
</List>
Vamos começar pelo <List>
Um componente List teria a seguinte estrutura:
function List({ children }) {
return (
<ul>
{children}
</ul>
)
}
export { List };
Depois o <Item>
No mesmo arquivo...
...
function Item({ children }) {
return (
<li>
{children}
</li>
)
}
...
E como criar o <List.Item>
?
E a resposta é o Object
. Mais precisamente o Object.assign
.
Ele tem diversas utilidades, e eu recomendo dar uma pesquisada melhor sobre ele, mas o uso dele que vamos usar aqui é pra criar um objeto que possui um "default" que é o List
e valor que é o Item
.
Também vamos mudar o nome do List
para Main
(esse Main é só um padrão que gosto de usar mas ele pode ser usado com outro nome).
function Main({ children }) {
return (
<ul>
{children}
</ul>
)
}
function Item({ children }) {
return (
<li>
{children}
</li>
)
}
const List = Object.assign(Main, {
Item, // Se tiver mais componentes é só ir incluindo aqui
});
export { List }
Tenho usado esse PATTERN a alguns meses e é ótimo para criar componentes, principalmente se estiver desenvolvendo um Design System, então comenta aí o que achou. Já conhecia esse pattern? Vai começar usar?
Autor: Dan Sousa
Dessa maneira eu sou obrigado a usar o List.Item?
Achei bastante interessante, nunca usei esse pattern, irei testar e retorno pra dar um feedback futuramente, obrigado pelo conteudo!
Eu ainda não conhecia esse pattern, achei muito interessante, com certeza vou testar! Parabéns pelo post Daniel! 👏
Sempre ouvi falarem que esse tipo de pattern se encaixa muito bem no React Native, mas nem tanto no ReactJS, em questões de boas praticas e/ou cultura dentro de uma empresa, o que vocês acham??
Muito legal.
Já conhecia esse padrão e utilizo bastante ele juntamente com a Context API
para compartilhar informações entre os componentes.
Eu escrevi um artigo sobre um outro padrão muito bom também.
Depois da uma olhada lá: Render Props Pattern [REACT]
Muito interessante esse Design Pattern. Eu já utilizei dessa forma conforme aprendi no curo React Avançado do Willian Justen. Ele utiliza:
export * as S from './styles';
Dessa forma pra colocar os componentes visuais na tela fica assim:
<S.Container>
<S.Title>Título da página</S.Title>
</S.Container>
Eu acho muito legal essa forma pois não precisamos ficar trocando de aba pra ver o nome que a gente deu pra um determinado estilo.
Eu já tinha visto essa prática em algumas libs antes, mas até então não imaginei que era algo como uma convensão de design pattern, muito interessante. O próprio Primer (lib do DS do GitHub, usado pelo TabNews) usa esse DP. Bom artigo introdutório para o assunto! 🙂
Eu acho esse padrão muito interessante, mas eu sempre fico pensando: Isso não deixaria o bundle final mais pesado? Precisaria de usar alguma prática de tree-shaking pra retirar os componentes que não vão ser usados desses objetos? Afinal, se você está carregando um único objeto com enésimos componentes, você consequentemente leva todos esses componentes, mesmo que você não esteja usando eles 🤔
Essa dúvida é a única coisa que me impede de começar a desenvolver nesse formato