Escribir una API para componentes React, parte 1: no cree accesorios conflictivos
Escribir una API para React Components, Parte 2: Dar nombres al comportamiento, no a la interacción
Escribir una API para componentes React, parte 3: el orden de los accesorios es importante
Escribir una API para React Components, Parte 4: ¡Cuidado con el Apropacalypse!
Escribir una API para React Components, Parte 5: solo use la composición
Escribimos API para componentes React, parte 6: creamos comunicación entre componentes
Hablemos del componente Avatar
.

<Avatar image="simons-cat.png" />
Los avatares se encuentran en todas partes en las aplicaciones y generalmente vienen en diferentes tamaños. Necesita un avatar grande para el perfil de usuario, uno pequeño en las listas desplegables y algunos intermedios.

Agreguemos el size
accesorio (accesorio para los tamaños).
No queremos darle al desarrollador la capacidad de especificar anchos y alturas arbitrarias; en cambio, queremos darle al desarrollador varios tamaños posibles.

<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" />
En el cosmos , todavía tenemos avatares para aplicaciones. Queremos que se vean un poco diferentes: un cuadrado redondeado en lugar de un círculo.
Parte de la creación de una buena API es dar a los desarrolladores la capacidad de pensar sobre los datos en lugar de diseñarlos; el diseño ya debería estar en el componente
Podemos agregar otro accesorio que distinga entre dos tipos de avatares. Un pequeño accesorio no puede doler, ¿verdad?

<Avatar type="user" image="simons-cat.png" /> <Avatar type="app" image="firebase.png" />
Se ve bien, ¿no?
Y sí, tenemos soporte de varios tamaños para el avatar de la aplicación, porque es el mismo componente. En general, no necesitamos esto, pero por qué no, ya que no nos costó 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" />
Hablemos de cómo el desarrollador realmente usará este componente en su aplicación. La información del usuario probablemente proviene de la API y contiene la URL del avatar. El desarrollador pasará esta información al componente Avatar
usando accesorios.
Y si el usuario aún no ha subido un avatar, queremos mostrar el valor predeterminado, lo mismo ocurre con el logotipo de la aplicación.

<Avatar type="user" image={props.user.avatar} /> <Avatar type="user" image={missing} /> <Avatar type="app" image={props.app.logo} /> <Avatar type="app" image={missing} />
La imagen predeterminada ya está incluida en el componente, por lo que no le pedimos al desarrollador la imagen de imagen predeterminada.
Este es un buen recurso, pero podemos hacer más.
Podemos mostrar las iniciales de un nombre de usuario con un fondo único (Gmail hizo popular esta plantilla, ayuda a distinguir rápidamente entre personas)

<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} />
Veamos todos los accesorios que admite nuestro componente:
Comenzamos con un componente de avatar simple, ¡pero ahora es compatible con todos estos accesorios y comportamientos!
Cuando ve un componente que admite muchos accesorios, probablemente esté tratando de hacer demasiadas cosas. Acabas de crear Apropcalypse .
Acuñó este concepto por Jenn Creighton .
Estamos tratando de hacer que nuestro componente Avatar
funcione para los usuarios y las aplicaciones, y al mismo tiempo que funcione con diferentes tamaños y diferentes opciones para el comportamiento alternativo.
También permite combinaciones extrañas que no se recomiendan para su uso, como un avatar de aplicación de texto de respaldo. Recuerde, este fue el consejo n.º 1: no cree accesorios conflictivos (consulte Escritura de la API para componentes React, parte 1: ¡no cree accesorios conflictivos )!
Bien, ¿cómo vamos a lidiar con esto? Crea dos componentes diferentes.
Consejo:
No tenga miedo de crear un nuevo componente en lugar de agregar accesorios y lógica adicional a un componente existente.
Primero, así es como se verá la API para dos componentes de avatar diferentes:

<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="" />
Hay varias cosas que vale la pena señalar en esta API:
- Pudimos eliminar funciones innecesarias, como el
size
, en AppAvatar
. - Redujimos el tamaño de nuestra API al mantener el mismo nombre de reserva (reserva) para los dos componentes.
¿Recuerdas el consejo número 2 de esta serie ? Queremos que los desarrolladores piensen en el comportamiento ( fallback
) y no en la interacción / implementación (iniciales o íconos) . Esto ayuda a los desarrolladores a aprender API y formas de usar componentes más rápido. - También podemos evitar cualquier accesorio conflictivo .
- Finalmente, redujimos el número de accesorios. Mira la mesa de utilería, se ha vuelto mucho más limpia:
UserAvatar:
AppAvatar:
Lo único que me molesta un poco en esta API es que, aunque ambos componentes tienen el mismo nombre y tipo para el fallback: string
(un repliegue con type string
es un string), uno de ellos toma dos letras para las iniciales, mientras que tiempo como otro es el nombre del icono.
Hablemos de implementación. Es tentador crear un componente BaseAvatar
que use UserAvatar
y AppAvatar
, mientras que algunos accesorios serán bloqueados.
function UserAvatar(props) { return ( <BaseAvatar image={props.image} type="user" initials={props.fallback} /> ) } render(<UserAvatar fallback="LA" />)
Y esto no es una mala idea en absoluto. Pero al principio es bastante difícil predecir lo que podríamos necesitar. Pronosticamos mal las demandas futuras.
Comience con dos componentes diferentes, y a medida que los desarrolle, puede comenzar a ver patrones similares y encontrar una buena abstracción. La falta de abstracción es mucho mejor que la abstracción incorrecta.
La duplicación es mejor que la abstracción incorrecta - Sandi Metz
Regrese a su código y encuentre el componente que requiere demasiados accesorios y vea si puede simplificarlo dividiéndolo en varios componentes.
Para estudio adicional:
- una conferencia de Jenn Creighton , donde habla sobre los Apropacalips
- Conferencia de Sandi Metz sobre duplicados y abstracciones