Escrevendo uma API para componentes React, parte 1: não crie objetos conflitantes
Escrevendo uma API para componentes de reação, parte 2: dê nomes ao comportamento, não à interação
Escrevendo uma API para componentes React, parte 3: a ordem dos adereços é importante
Escrevendo uma API para reagir componentes, parte 4: Cuidado com o Apropacalypse!
Escrevendo uma API para reagir componentes, parte 5: apenas usar composição
Escrevemos API para componentes React, parte 6: criamos comunicação entre componentes
Vamos falar sobre o componente Avatar
.

<Avatar image="simons-cat.png" />
Avatares são encontrados em todos os lugares nos aplicativos e geralmente vêm em tamanhos diferentes. Você precisa de um avatar grande para o perfil do usuário, um pequeno nas listas suspensas e alguns intermediários.

Vamos adicionar o size
suporte (suporte para tamanhos).
Não queremos dar ao desenvolvedor a capacidade de especificar larguras e alturas arbitrárias; em vez disso, queremos fornecer ao desenvolvedor vários tamanhos possíveis.

<Avatar size="xsmall" image="simons-cat.png" /> <Avatar size="small" image="simons-cat.png" /> <Avatar size="medium" image="simons-cat.png" /> <Avatar size="large" image="simons-cat.png" /> <Avatar size="xlarge" image="simons-cat.png" />
No cosmos , ainda temos avatares para aplicativos. Queremos que eles pareçam um pouco diferentes - um quadrado arredondado em vez de um círculo.
Parte da criação de uma boa API é oferecer aos desenvolvedores a capacidade de pensar nos dados em vez de no design - o design já deve estar no componente
Podemos adicionar outro objeto que distingue entre dois tipos de avatares. Um pequeno suporte não pode machucar, certo?

<Avatar type="user" image="simons-cat.png" /> <Avatar type="app" image="firebase.png" />
Parece bom, não é?
E sim, obtemos suporte de vários tamanhos para o avatar do aplicativo, porque é o mesmo componente. Em geral, não precisamos disso, mas por que não, uma vez que não nos custou nada

<Avatar type="app" size="xsmall" image="firebase.png" /> <Avatar type="app" size="small" image="firebase.png" /> <Avatar type="app" size="medium" image="firebase.png" /> <Avatar type="app" size="large" image="firebase.png" /> <Avatar type="app" size="xlarge" image="firebase.png" />
Vamos falar sobre como o desenvolvedor realmente usará esse componente em seu aplicativo. As informações do usuário provavelmente provêm da API e contêm a URL do avatar. O desenvolvedor passará essas informações para o componente Avatar
usando adereços.
E se o usuário ainda não fez o upload de um avatar, queremos mostrar o valor padrão, o mesmo vale para o logotipo do aplicativo.

<Avatar type="user" image={props.user.avatar} /> <Avatar type="user" image={missing} /> <Avatar type="app" image={props.app.logo} /> <Avatar type="app" image={missing} />
A imagem padrão já está incluída no componente, portanto, não solicitamos ao desenvolvedor a imagem da imagem padrão.
Esta é uma boa alternativa, mas podemos fazer mais.
Podemos mostrar as iniciais de um nome de usuário com um plano de fundo exclusivo (o Gmail tornou esse modelo popular, ajuda a distinguir rapidamente as pessoas)

<Avatar type="user" image={props.user.avatar} /> <Avatar type="user" image={missing} /> <Avatar type="user" initials={props.user.intials} image={missing} /> <Avatar type="app" image={props.app.logo} /> <Avatar type="app" image={missing} /> <Avatar type="app" icon={props.app.type} image={missing} />
Vamos dar uma olhada em todos os acessórios que nosso componente suporta:
Começamos com um componente de avatar simples, mas agora ele suporta todos esses adereços e comportamento!
Quando você vê um componente que suporta muitos adereços, provavelmente está tentando fazer muitas coisas. Você acabou de criar Apropcalypse .
Cunhou esse conceito por Jenn Creighton .
Estamos tentando fazer nosso componente Avatar
funcionar para usuários e aplicativos, enquanto trabalhamos com tamanhos diferentes e comportamentos de fallback diferentes.
Também permite combinações estranhas que não são recomendadas para uso, como um avatar de aplicativo de texto de backup. Lembre-se, essa foi a dica 1 - não crie objetos conflitantes (consulte Escrevendo a API para componentes React, parte 1: não crie objetos conflitantes )!
Ok, como vamos lidar com isso? Crie dois componentes diferentes.
Dica:
Não tenha medo de criar um novo componente em vez de adicionar adereços e lógica adicional a um componente existente.
Primeiro, eis a aparência da API para dois componentes diferentes de avatar:

<UserAvatar size="large" image="simons-cat.png" /> <UserAvatar size="large" image="" /> <UserAvatar size="large" fallback="LA" image="" /> <AppAvatar image="firebase.png" /> <AppAvatar image="" /> <AppAvatar fallback="database" image="" />
Há várias coisas que vale a pena notar nesta API:
- Conseguimos remover recursos desnecessários, como
size
, no AppAvatar
. - Reduzimos o tamanho da nossa API mantendo o mesmo nome de fallback (fallback) para os dois componentes.
Lembra da dica número 2 desta série ? Queremos que os desenvolvedores pensem no comportamento ( fallback
), e não na interação / implementação (iniciais ou ícones) . Isso ajuda os desenvolvedores a aprender APIs e maneiras de usar componentes mais rapidamente. - Também podemos evitar adereços conflitantes .
- Por fim, reduzimos o número de adereços. Olhe para a tabela de objetos, tornou-se muito mais limpa:
UserAvatar:
AppAvatar:
A única coisa que me incomoda um pouco nessa API é que, embora ambos os componentes tenham o mesmo nome e tipo para fallback: string
(um fallback com type string
é uma string), um deles recebe duas letras para as iniciais, enquanto time como outro é o nome do ícone.
Vamos falar sobre implementação. É tentador criar um componente BaseAvatar
que o UserAvatar
e o UserAvatar
usarão, enquanto alguns acessórios serão bloqueados.
function UserAvatar(props) { return ( <BaseAvatar image={props.image} type="user" initials={props.fallback} /> ) } render(<UserAvatar fallback="LA" />)
E isso não é uma má idéia. Mas é muito difícil desde o início prever o que precisamos. Prevemos mal demandas futuras.
Comece com dois componentes diferentes e, à medida que você os desenvolve, pode começar a ver padrões semelhantes e encontrar uma boa abstração. A falta de abstração é muito melhor que a abstração incorreta.
Duplicação é melhor que abstração incorreta - Sandi Metz
Volte ao seu código e encontre o componente que possui muitos adereços e veja se você pode simplificá-lo dividindo-o em vários componentes.
Para um estudo mais aprofundado:
- uma palestra de Jenn Creighton , onde ela fala sobre os Apropacalips
- Sandi Metz palestra sobre duplicatas e abstrações