Écriture d'une API pour les composants React, partie 1: ne créez pas d'accessoires conflictuels
Écriture d'une API pour les composants React, partie 2: donner des noms au comportement, pas à l'interaction
Écriture d'une API pour les composants React, partie 3: l'ordre des accessoires est important
Écriture d'une API pour React Components, Partie 4: Méfiez-vous de l'Apropacalypse!
Écriture d'une API pour les composants React, partie 5: il suffit d'utiliser la composition
Nous écrivons API pour les composants React, partie 6: nous créons la communication entre les composants
Parlons du composant Avatar
.

<Avatar image="simons-cat.png" />
Les avatars se trouvent partout dans les applications et se présentent généralement en différentes tailles. Vous avez besoin d'un grand avatar pour le profil utilisateur, un petit dans les listes déroulantes et quelques intermédiaires.

Ajoutons la size
hélice (accessoire pour les tailles).
Nous ne voulons pas donner au développeur la possibilité de spécifier des largeurs et des hauteurs arbitraires; au lieu de cela, nous voulons donner au développeur plusieurs tailles possibles.

<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" />
Dans le cosmos , nous avons encore des avatars pour les applications. Nous voulons qu'ils aient l'air un peu différent - un carré arrondi au lieu d'un cercle.
Une partie de la création d'une bonne API consiste à donner aux développeurs la possibilité de penser aux données plutôt qu'à la conception - la conception devrait déjà être dans le composant
Nous pouvons ajouter un autre accessoire qui distingue deux types d'avatars. Un petit accessoire ne peut pas faire de mal, non?

<Avatar type="user" image="simons-cat.png" /> <Avatar type="app" image="firebase.png" />
Ça a l'air bien, non?
Et oui, nous obtenons un support multi-taille pour l'avatar de l'application, car il s'agit du même composant. En général, nous n'en avons pas besoin, mais pourquoi pas, car cela ne nous a rien coûté

<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" />
Parlons de la façon dont le développeur utilisera réellement ce composant dans son application. Les informations utilisateur proviennent probablement de l'API et contiennent l'URL de l'avatar. Le développeur transmettra ces informations au composant Avatar
aide d'accessoires.
Et si l'utilisateur n'a pas encore téléchargé d'avatar, nous voulons afficher la valeur par défaut, il en va de même pour le logo de l'application.

<Avatar type="user" image={props.user.avatar} /> <Avatar type="user" image={missing} /> <Avatar type="app" image={props.app.logo} /> <Avatar type="app" image={missing} />
L'image par défaut est déjà incluse dans le composant, nous ne demandons donc pas au développeur l'image d'image par défaut.
C'est une bonne solution de rechange, mais nous pouvons faire plus.
Nous pouvons afficher les initiales d'un nom d'utilisateur avec un arrière-plan unique (Gmail a rendu ce modèle populaire, il permet de distinguer rapidement les personnes)

<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} />
Regardons tous les accessoires que notre composant prend en charge:
Nous avons commencé avec un simple composant avatar, mais maintenant il prend en charge tous ces accessoires et comportements!
Lorsque vous voyez un composant qui prend en charge de nombreux accessoires, il essaie probablement de faire trop de choses. Vous venez de créer Apropcalypse .
Inventé ce concept par Jenn Creighton .
Nous essayons de faire fonctionner notre composant Avatar
pour les utilisateurs et les applications, tout en travaillant avec des tailles et des options différentes pour le comportement de secours.
Il permet également des combinaisons étranges dont l'utilisation n'est pas recommandée, comme un avatar d'application de sauvegarde de texte. Rappelez-vous, c'était le conseil n ° 1 - ne créez pas d'accessoires conflictuels (voir Écriture de l'API pour les composants React, partie 1: ne créez pas d'accessoires conflictuels )!
D'accord, comment allons-nous gérer cela? Créez deux composants différents.
Astuce:
N'ayez pas peur de créer un nouveau composant au lieu d'ajouter des accessoires et une logique supplémentaire à un composant existant.
Tout d'abord, voici à quoi ressemblera l'API pour deux composants d'avatar différents:

<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="" />
Il y a plusieurs choses à noter dans cette API:
- Nous avons pu supprimer des fonctionnalités inutiles, telles que la
size
, dans AppAvatar
. - Nous avons réduit la taille de notre API en conservant le même nom de secours (secours) pour les deux composants.
Rappelez-vous le conseil numéro 2 de cette série ? Nous voulons que les développeurs pensent au comportement ( fallback
) et non à l'interaction / implémentation (initiales ou icônes) . Cela aide les développeurs à apprendre plus rapidement les API et les façons d'utiliser les composants. - Nous pouvons également éviter tout accessoire conflictuel .
- Enfin, nous avons réduit le nombre d'accessoires. Regardez le tableau des accessoires, il est devenu beaucoup plus propre:
UserAvatar:
AppAvatar:
La seule chose qui me dérange un peu dans cette API est que, bien que les deux composants aient le même nom et le même type pour fallback: string
(un fallback avec le type string
est une chaîne), l'un d'eux prend deux lettres pour les initiales, tandis que temps comme un autre est le nom de l'icône.
Parlons de la mise en œuvre. Il est tentant de créer un composant BaseAvatar
que UserAvatar
et UserAvatar
utiliseront, tandis que certains accessoires seront bloqués.
function UserAvatar(props) { return ( <BaseAvatar image={props.image} type="user" initials={props.fallback} /> ) } render(<UserAvatar fallback="LA" />)
Et ce n'est pas du tout une mauvaise idée. Mais il est assez difficile au tout début de prévoir ce dont nous pourrions avoir besoin. Nous prédisons mal les demandes futures.
Commencez avec deux composants différents, et au fur et à mesure que vous les développez, vous pouvez commencer à voir des modèles similaires et à trouver une bonne abstraction. Le manque d'abstraction est bien meilleur qu'une abstraction incorrecte.
La duplication vaut mieux qu'une abstraction incorrecte - Sandi Metz
Revenez à votre code et trouvez le composant qui prend trop d'accessoires et voyez si vous pouvez le simplifier en le divisant en plusieurs composants.
Pour complément d'étude:
- une conférence de Jenn Creighton , où elle parle des Apropacalips
- Conférence de Sandi Metz sur les doublons et les abstractions