É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
Nous avons un composant icône:

<Badge count={12} />
Vous les avez vus dans diverses applications, ils affichent le nombre d'objets sous forme de nombre.

Le badge cosmos (icône) a plusieurs couleurs pour chaque contexte spécifique (information, danger, etc.)

<Badge count={12} appearance="information" /> <Badge count={12} appearance="success" /> <Badge count={12} appearance="default" /> <Badge count={12} appearance="warning" /> <Badge count={12} appearance="danger" />
Cette interface utilisateur a un autre composant similaire - Label
.

Il a également plusieurs couleurs pour chaque contexte:

<Label text="private" appearance="information" /> <Label text="private" appearance="success" /> <Label text="private" appearance="default" /> <Label text="private" appearance="warning" /> <Label text="private" appearance="danger" />
Regardez ces deux composants et dites une bonne et une mauvaise chose à propos de leur API (à propos de leurs accessoires)

<Badge count={12} appearance="information" /> <Label text="private" appearance="information" />
À quoi bon
Les deux composants ont le même accessoire d'apparence: l' appearance
, c'est super. De plus, ils ont les mêmes options pour cet accessoire! Si vous savez comment utiliser l' appearance
dans Badge
, vous savez déjà comment utiliser l' appearance
dans Label
Efforcez-vous d'obtenir des accessoires cohérents entre les composants
Astuce n ° 2 de la rédaction d'une API pour les composants React, partie 2: Donner des noms au comportement, pas à l'interaction
Ce qui est mauvais
La façon dont ils prennent leur signification est différente. Ils ont tous deux leur propre option.
Compter, count
, est logique dans le cadre du composant Badge
, mais en tenant compte de tous les autres composants, il s'agit d'une API supplémentaire dont votre équipe et vos utilisateurs (développeurs) devront se souvenir.
Améliorons cette API
Pour être cohérent, j'appellerai ce content
accessoire, c'est le nom le plus courant que je pourrais trouver - plus général que simplement une étiquette, du texte ou une valeur.

<Badge content="12" appearance="information" /> <Label content="private" appearance="information" />
Nous avons perdu quelques détails, mais avons obtenu beaucoup de cohérence. Nous pouvons toujours définir le type de valeur avec prop-types , donc je pense que c'est un bon compromis.
Mais attendez, dans React, il existe déjà un accessoire de content
polyvalent, il s'appelle les children
- un enfant.
Ne réinventez pas les props.children.
Si vous avez défini des accessoires qui acceptent des données arbitraires qui ne sont pas basées sur une structure de données, il est probablement préférable d'utiliser la composition - Brent Jackson
Voici la pointe de cet article - Lorsque vous choisissez entre une composition et des accessoires, choisissez une composition .
Refactorisons cette API avec les children
, les enfants:

<Badge appearance="information">12 </Badge> <Label appearance="information">Private </Label>
Ça a l'air super.
Bonus: lorsque vous utilisez des children
au lieu de prop, le développeur utilisant ce composant obtient plus de flexibilité sans avoir à changer le composant.
Par exemple, voici
, dans celui-ci, je veux ajouter une icône devant le texte.

En utilisant des children
je peux ajouter une icône à ce
sans revenir à ce composant ni le modifier.
// - <Alert type="warning" icon="warning" text="This is an important message!" /> // <Alert type="warning"> <Icon name="warning" /> This is an important message! </Alert>
Par coïncidence, lorsque j'ai écrit ce texte, j'ai vu un tweet de Brad Frost :
Hé, les amis de React, ont besoin d'un peu d'aide. Je continue à courir dans ce modèle où certains composants (en particulier les listes) peuvent être divisés en composants plus petits ou contrôlés en passant un objet. Quelle option est la meilleure?

Semble familier?
Tout d'abord, n'utilisons pas de text
accessoire et utilisons plutôt des children
.
// : <Breadcrumb text="Home" href="/child" /> // : <Breadcrumb href="/child">Home</Breadcrumb>
Maintenant que nous avons compris cela, parlons de ces deux options d'API.
Comme ce n'est pas difficile à deviner, j'aime le premier.
- Vous n'avez pas besoin de penser à quel prop -
text
est appelé? label
? Ce ne sont que des children
. - Vous pouvez y ajouter votre nom de
className
ou votre target
si nécessaire. Pour la deuxième option, vous devez vous assurer qu'elle prend en charge ces propriétés ou les transmet simplement à l'élément de base. - Cela vous permet d'envelopper l'enfant dans un contexte ou dans un composant de niveau supérieur.
Exception à la règle:
Que faire si Brad veut empêcher le développeur de définir les paramètres que j'ai mentionnés ci-dessus? Alors donner plus de flexibilité au développeur, dans son cas, serait une erreur!
Voici ma réponse à Brad .
Plus d'exemples
Voici quelques exemples supplémentaires de la façon dont cette astuce peut améliorer votre code, mon dernier favori.
Les formulaires sont un excellent exemple d'utilisation, nous voulons contrôler la mise en page du formulaire, afficher les erreurs, etc. Mais en même temps, nous ne voulons pas perdre des opportunités d'expansion.
// #1 <FormTextInput type="text" label="Name" id="name-input" /> // id, // label input? // #2 <FormField> <Label>Field label</Label> <TextInput id="name-input" type="text" placeholder="What's your name?" /> </FormField> // #3 <FormField label="Field label"> <TextInput id="name-input" type="text" placeholder="What's your name?" /> </FormField>
Ce dernier exemple est particulièrement intéressant.
Parfois, vous avez besoin d'un composant qui sera utilisé dans des situations très différentes. Il n’est pas facile de créer un composant qui soit flexible et qui ait toujours une API simple.
C'est là que l'inversion du contrôle vient à la rescousse - laissez l'utilisateur du composant décider quoi rendre. Dans le monde React, ce motif est appelé motif de rendu .
Le composant render prop prend une fonction qui renvoie un élément React et l'appelle au lieu d'implémenter son propre rendu.
de la documentation React Render-props
L'un des exemples les plus populaires d'accessoires de rendu est l'API Context officielle.
Dans l'exemple suivant, le composant App
contrôle les données, mais ne contrôle pas son rendu; il transmet ce contrôle au composant Counter
.
Avez-vous remarqué quelque chose d'intéressant dans cette API Consumer
?
Au lieu de créer une nouvelle API, il utilise des children
pour accepter une fonction qui lui dit comment effectuer le rendu!
// <Consumer render={value => ( <div className="counter">the count is: {value}</div> )} /> // <Consumer> {value => ( <div className="counter">the count is: {value}</div> )} </Consumer>
Revenez à votre code et trouvez le composant qui accepte tous les accessoires lorsqu'il peut facilement utiliser des children
.