Écriture d'une API pour les composants React, partie 5: il suffit d'utiliser la composition

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


<Badge count={12} /> 

Vous les avez vus dans diverses applications, ils affichent le nombre d'objets sous forme de nombre.


github-1


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


badge-2


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


github-2


Il a également plusieurs couleurs pour chaque contexte:


label-2


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


ensemble 2


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


ensemble 2


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


ensemble 2


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


alerte


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?

code


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.


  1. Vous n'avez pas besoin de penser à quel prop - text est appelé? label ? Ce ne sont que des children .
  2. 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.
  3. 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 .


 //    const MyContext = React.createContext() //    //    function App() { return ( <MyContext.Provider value="5"> <Counter /> </MyContext.Provider> ) } //    //   function Counter() { return ( <MyContext.Consumer> {value => ( <div className="counter">the count is: {value}</div> )} </MyContext.Consumer> ) } 

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 .

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


All Articles