Escrevendo uma API para reagir componentes, parte 4: Cuidado com o Apropacalypse

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-1


 <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.


avatares do github


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-2


 <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-3


 <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-4


 <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-6


 <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-7


 <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:


primeiro nomea descriçãotipovalor padrão
imageURL da imagemstring-
sizetamanho do avatarstring: [xsmall, small, medium, large, xlarge]small
typetipo de avatarstring: [user, app]user
initialsiniciais do usuário como substitutostring-
iconícone para exibir como substitutostring: [list of icons]-

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:


avatar-7


 <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:


  1. Conseguimos remover recursos desnecessários, como size , no AppAvatar .
  2. 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.
  3. Também podemos evitar adereços conflitantes .
  4. Por fim, reduzimos o número de adereços. Olhe para a tabela de objetos, tornou-se muito mais limpa:

UserAvatar:


primeiro nomea descriçãotipovalor padrão
imageURL da imagemstring-
sizetamanho do avatarstring: [xsmall, small, medium, large, xlarge]small
fallbackiniciais do usuário como substitutostring-

AppAvatar:


primeiro nomea descriçãotipovalor padrão
imageURL da imagemstring-
fallbackícone como substitutostring: [list of icons]-

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:


  1. uma palestra de Jenn Creighton , onde ela fala sobre os Apropacalips
  2. Sandi Metz palestra sobre duplicatas e abstrações

Source: https://habr.com/ru/post/pt459414/


All Articles