
Écrit par Kristofer Selbekk , en collaboration avec Caroline Odden . Basé sur une conférence avec le même nom et les mêmes personnes lors de la réunion ReactJS à Oslo en juin 2019.
Du traducteur - le nom original de The 10 Component Commandments ne mentionne pas React, mais la plupart des exemples et recommandations se rapportent spécifiquement à la réaction.En outre, l'article est présenté sous la balise react et les développeurs ont écrit la réaction .
Il n'est pas facile de créer des composants que de nombreux développeurs utiliseront. Vous devez soigneusement considérer les accessoires à utiliser si ces accessoires font partie de l'API publique.
Dans cet article, nous ferons une brève introduction à certaines des meilleures pratiques pour développer l'API dans son ensemble, ainsi que dix commandements que vous pouvez utiliser pour créer des composants que vos collègues développeurs seront heureux d'utiliser.

Qu'est-ce qu'une API?
Une API - ou une interface de programmation d'application - est l'endroit où deux morceaux de code se rencontrent. Il s'agit de la surface de contact entre votre code et le reste du monde. Nous appelons cette surface une interface. Il s'agit d'un ensemble spécifique d'actions ou de points de données avec lesquels vous pouvez interagir.
L'interface entre la classe et le code qui appelle cette classe est également une API. Vous pouvez appeler les méthodes de la classe pour recevoir des données ou exécuter les fonctions qui y sont contenues.
Suivant le même principe, les accessoires que votre composant accepte, c'est son API . C'est ainsi que les développeurs interagissent avec votre composant.
Quelques meilleures pratiques de conception d'API
Alors, quelles règles et considérations s'appliquent lors du développement d'une API? Eh bien, nous avons fait un peu de recherche, et il s'est avéré qu'il y a beaucoup de grandes ressources à ce sujet. Nous en avons choisi deux - Josh Tauberer - "Qu'est-ce qui fait une bonne API?" et un article de Ron Kurir avec le même titre - et est venu à ces quatre pratiques.
Versions stables
L'une des choses les plus importantes à considérer lors de la création d'une API est de la garder aussi stable que possible. Le nombre de changements critiques doit être minimal. Si vous devez apporter des modifications critiques, assurez-vous d'écrire des guides de mise à jour détaillés et, si possible, d'écrire un code de mod qui automatise ce processus pour les développeurs.
Messages d'erreur descriptifs
Chaque fois qu'une erreur se produit lors de l'appel de votre API, vous devez faire tout votre possible pour expliquer ce qui n'a pas fonctionné et comment y remédier. Si vous réprimandez l'utilisateur avec des messages comme "abus" et ne donnez aucune explication, votre API laissera une mauvaise impression.
Écrivez plutôt des erreurs descriptives qui aident l'utilisateur à déterminer comment il utilise votre API.
Minimisez les surprises pour les développeurs
Les développeurs sont des créatures fragiles, et vous ne devriez pas leur faire peur lorsqu'ils utilisent votre API. En d'autres termes, rendez votre API aussi intuitive que possible. Vous y arriverez si vous suivez les meilleures pratiques et les conventions de dénomination existantes.
De plus, votre code doit toujours être cohérent. Si vous utilisez les noms logiques des propriétés avec is
ou has
en un seul endroit, mais que vous les sautez plus loin, cela déroutera les gens.
Réduire la surface de l'API
Votre API doit également être minimisée. De nombreuses fonctionnalités sont excellentes, mais plus la surface de votre API (surface API) est petite, moins les développeurs devront l'étudier pour commencer à travailler de manière productive avec elle. Grâce à cela, votre API sera perçue comme facile à utiliser!
Il existe toujours un moyen de contrôler la taille de vos API. L'un d'eux consiste à refactoriser la nouvelle API de l'ancienne.
Les dix commandements des composants Web

Donc, ces quatre règles d'or fonctionnent bien pour l'API REST et pour les anciennes pièces procédurales sur Pascal - mais comment les transférer dans le monde moderne de React?
Comme nous l'avons dit précédemment, les composants ont leur propre API. Nous les appelons des props
, et c'est avec leur aide que les données sont transférées aux composants. Comment structurer les accessoires de manière à ne violer aucune des règles ci-dessus?
Nous avons créé cette liste de dix règles d'or à suivre lors de la création de vos composants. Nous espérons qu'ils vous seront utiles.
1. Documenter l'utilisation des composants
Si la façon dont vous souhaitez utiliser votre composant n'est pas documentée, ce composant est inutile. Eh bien, presque inutile, vous pouvez toujours regarder sa mise en œuvre, mais peu de gens aiment le faire.
Il existe de nombreuses façons de documenter vos composants, mais nous vous recommandons de faire attention à ces trois:
Les deux premiers vous donnent un endroit pour travailler lors du développement de vos composants, et le troisième vous permet d'écrire de la documentation sous forme libre à l'aide de MDX
Peu importe ce que vous choisissez, documentez toujours l'API elle-même et comment et quand vos composants doivent être utilisés . La dernière partie est critique dans les bibliothèques à usage général - pour que les gens utilisent correctement un bouton ou une grille de disposition dans un contexte donné.
2. Activer la sémantique contextuelle
HTML est un langage pour structurer l'information de manière sémantique. Seulement ici, la plupart de nos composants sont constitués de balises <div />
. Cela a du sens - les composants universels ne peuvent pas savoir à l'avance ce qu'ils seront, peut-être <article />
, ou <section />
, ou <aside />
- mais cette situation est loin d'être idéale.
Il existe une autre option, laissez simplement vos composants accepter prop as
, et ainsi déterminer quel élément DOM sera rendu. Voici un exemple de mise en œuvre de ceci:
function Grid({ as: Element, ...props }) { return <Element className="grid" {...props} /> } Grid.defaultProps = { as: 'div', };
Nous renommons prop as
variable Element
et nous l'utilisons dans notre JSX. Nous donnons une valeur div
par défaut commune si nous n'avons pas de balise HTML plus sémantique à transmettre.
Lorsque vient le temps d'utiliser le composant <Grid />
, vous pouvez simplement passer la bonne balise:
function App() { return ( <Grid as="main"> <MoreContent /> </Grid> ); }
Cela fonctionne également avec les composants React. Par exemple, si vous souhaitez que le composant <Button />
rende le React Router <Link />
:
<Button as={Link} to="/profile"> Go to Profile </Button>
3. Évitez les accessoires booléens
Les accessoires logiques sont, comme, une bonne idée. Ils peuvent être utilisés sans valeur, il a donc l'air très élégant:
<Button large>BUY NOW!</Button>
Mais bien que cela semble agréable, les propriétés logiques ne permettent que deux possibilités. On ou off Visible ou caché. 1 ou 0.
Chaque fois que vous commencez à introduire des propriétés logiques pour des choses comme la taille, les options, les couleurs ou tout ce qui peut être autre chose qu'un choix binaire, vous avez des problèmes.
<Button large small primary disabled secondary> ?? </Button>
En d'autres termes, les propriétés logiques ne sont souvent pas adaptées à l'évolution des exigences. Au lieu de cela, pour les valeurs qui peuvent devenir autre chose qu'une sélection binaire, il est préférable d'utiliser des valeurs énumérées, telles que des chaînes.
<Button variant="primary" size="large"> </Button>
Cela ne signifie pas que les propriétés logiques ne peuvent pas être utilisées du tout. Tu peux! L'hélice disabled
, que j'ai répertoriée ci-dessus, devrait toujours être logique - car il n'y a pas d'état intermédiaire entre l'activation et la désactivation. Ne laissez que les propriétés booléennes pour un choix vraiment binaire.
4. Utilisez des props.children
React a quelques propriétés spéciales qui sont traitées différemment des autres. L'une de ces key
est nécessaire pour suivre l'ordre des éléments de la liste. Et un autre tel accessoire spécial est les children
.
Tout ce que vous mettez entre les balises d'ouverture et de fermeture du composant est placé à l'intérieur de l' props.children
. Et vous devez l'utiliser aussi souvent que possible.
Pourquoi? Parce que c'est beaucoup plus facile que d'avoir du content
prop pour le contenu ou quelque chose comme ça qui ne prend généralement que des valeurs simples, comme le texte.
<TableCell content="Some text" /> // <TableCell>Some text</TableCell>
Il y a plusieurs avantages à utiliser des props.children
. Tout d'abord, cela ressemble à la façon dont le HTML standard fonctionne. Deuxièmement, vous pouvez transférer librement ce que vous voulez! Au lieu d'ajouter des accessoires tels que leftIcon
et rightIcon
à votre composant, passez-les simplement dans le cadre de props.children
:
<TableCell> <ImportantIcon /> Some text </TableCell>
Vous pouvez faire valoir que votre composant n'a besoin que de rendre du texte brut, et dans certains cas, il l'est. Jusqu'à un certain point. En utilisant props.children
, vous garantissez que votre API sera prête à changer les exigences.
5. Laissez le parent s'accrocher à la logique interne
Parfois, nous créons des composants avec beaucoup de logique et d'états internes - par exemple, des diagrammes à saisie semi-automatique ou interactifs.
De tels composants souffrent souvent de trop d'API, l'une des raisons en est le grand nombre de cas d'utilisation différents qui s'accumulent avec le développement du projet.
Mais que se passe-t-il si nous pouvions simplement fournir un accessoire unique et standardisé qui permet au développeur de contrôler, de répondre ou simplement de changer le comportement par défaut du composant?
Kent Dodds a écrit un excellent article sur le concept de réducteurs d'État. Voici un article sur le concept lui - même , ainsi qu'un article sur la façon de l' implémenter pour les hooks React .
En bref, il s'agit d'un modèle de transfert de fonction de réduction d'état vers votre composant, qui permettra au développeur d'accéder à toutes les actions effectuées à l'intérieur de votre composant. Vous pouvez changer d'état ou même provoquer des effets secondaires. C'est un excellent moyen de fournir un haut niveau de personnalisation, sans aucun accessoire .
Voici à quoi cela pourrait ressembler:
function MyCustomDropdown(props) { const stateReducer = (state, action) => { if (action.type === Dropdown.actions.CLOSE) { buttonRef.current.focus(); } }; return ( <> <Dropdown stateReducer={stateReducer} {...props} /> <Button ref={buttonRef}>Open</Button> </> }
Soit dit en passant, vous pouvez créer des moyens plus simples de répondre aux événements. L'utilisation de l' onClose
dans l'exemple précédent est susceptible de rendre l'utilisation du composant plus pratique. Utilisez le modèle "réducteur d'état" si nécessaire.
6. Utilisez l'opérateur d'épandage pour les accessoires restants
Chaque fois que vous créez un nouveau composant, assurez-vous d'appliquer les points de suspension aux accessoires restants et de les envoyer à l'élément pour lequel cela a du sens.
Vous n'avez pas besoin de continuer à ajouter des accessoires à votre composant, qui seront simplement transmis au composant ou à l'élément de base. Cela rendra votre API plus stable en éliminant le besoin de nombreuses erreurs de petite version lorsque le prochain développeur a besoin d'un nouvel écouteur d'événements ou d'une balise ARIA.
Vous pouvez le faire comme ceci:
function ToolTip({ isVisible, ...rest }) { return isVisible ? <span role="tooltip" {...rest} /> : null; }
Chaque fois que votre composant transmet prop à votre implémentation, comme un nom de classe ou onClick
gestionnaire onClick
, assurez-vous qu'un autre développeur peut faire de même. Dans le cas d'une classe, vous pouvez simplement ajouter la classe prop en utilisant la bibliothèque de noms de classe npm (ou simplement la concaténation de chaînes):
import classNames from 'classnames'; function ToolTip(props) { return ( <span {...props} className={classNames('tooltip', props.tooltip)} /> }
Dans le cas des gestionnaires de clics et autres rappels, vous pouvez les combiner en une seule fonction à l'aide d'un petit utilitaire. Voici une façon de procéder:
function combine(...functions) { return (...args) => functions .filter(func => typeof func === 'function') .forEach(func => func(...args)); }
Ici, nous créons une fonction qui accepte une liste de fonctions pour les combiner. Il renvoie un nouveau rappel, qui les appelle tous tour à tour avec les mêmes arguments.
Cette fonction peut être utilisée de cette façon:
function ToolTip(props) { const [isVisible, setVisible] = React.useState(false); return ( <span {...props} className={classNames('tooltip', props.className)} onMouseIn={combine(() => setVisible(true), props.onMouseIn)} onMouseOut={combine(() => setVisible(false), props.onMouseOut)} /> ); }
7. Utilisez les valeurs par défaut
Assurez-vous de donner suffisamment de valeurs par défaut (valeurs par défaut) à vos accessoires. Ainsi, vous réduirez le nombre d'accessoires obligatoires. Cela simplifiera considérablement votre API.
Prenons, par exemple, le gestionnaire onClick
. Si votre code n'a pas besoin de ce gestionnaire, utilisez la fonction vide (noop-function) comme accessoire par défaut. De cette façon, vous pouvez l'appeler dans votre code comme s'il était toujours transmis.
Un autre exemple pourrait être pour la saisie utilisateur. Supposons que la chaîne d'entrée est une chaîne vide, sauf indication contraire. Cela vous permettra de vous assurer que vous avez toujours affaire à un objet chaîne, et non à quelque chose d'indéfini ou de nul.
8. Pas besoin de renommer les attributs HTML
HTML en tant que langue a ses propres accessoires - ou attributs, et c'est lui-même une API pour les éléments HTML. Alors pourquoi ne pas continuer à utiliser cette API?
Comme nous l'avons mentionné précédemment, minimiser la surface de l'API et son intuitivité sont des méthodes utiles pour améliorer l'API de vos composants. Donc, au lieu de créer votre propre accessoire screenReaderLabel
, pourquoi ne pas simplement utiliser une aria-label
existante?
Évitez de renommer les attributs HTML existants pour votre propre "facilité d'utilisation". Vous ne remplacez même pas l'API existante - vous ajoutez simplement la vôtre par-dessus. Les gens peuvent toujours passer l' aria-label
avec votre screenReaderLabel
screenReaderLabel - et quelle devrait être la valeur finale alors?
Assurez-vous également de ne jamais remplacer les attributs HTML dans vos composants. Un bon exemple est l'attribut type
de l'élément <button />
. Il peut être submit
(par défaut), button
ou reset
. Cependant, de nombreux développeurs redéfinissent cet accessoire pour désigner le type visuel du bouton ( primary
, cta
, etc.).
Si vous utilisez un tel accessoire, vous devrez ajouter un remplacement pour l'attribut true type
. Cela conduira à la confusion, au doute et à la gêne de la part des développeurs.
Croyez-moi - j'ai fait cette erreur encore et encore - si vous la faites, vous devrez la démêler pendant longtemps.
9. Écrivez les types d'accessoires (ou seulement les types)
Aucune documentation ne sera aussi bonne que la documentation vivant dans votre code. React est livré avec un excellent moyen de déclarer vos API à l'aide du package prop-types
. Utilisez-le.
Vous pouvez spécifier toutes les exigences de format pour vos accessoires obligatoires et facultatifs, et vous pouvez les améliorer avec des commentaires JSDoc .
Si vous ne spécifiez pas d'accessoires obligatoires ou ne transmettez pas de valeur non valide ou inattendue, au moment de l'exécution, vous recevrez un avertissement dans la console. Cela aide beaucoup pendant le développement et peut être retiré de la production.
Si vous écrivez vos applications React en TypeScript ou en utilisant Flow, vous obtenez la documentation de l'API en tant que fonction de langage. Cela améliore encore le support des outils de développement et simplifie le travail.
Si vous n'utilisez pas vous-même du code JavaScript typé, vous devez toujours envisager de fournir des définitions de type aux développeurs qui l'utilisent. Il leur sera alors beaucoup plus facile d'utiliser vos composants.
10. Conception pour les développeurs
Enfin, la règle la plus importante à suivre. Assurez-vous que votre API et votre travail avec vos composants sont optimisés pour les développeurs qui l'utiliseront.
Une façon de simplifier le travail d'un développeur consiste à lui faire part de ses commentaires sur une utilisation inappropriée. Faites cela avec des messages d'erreur, mais aussi, mais uniquement pendant le développement, avec des avertissements qu'il existe des moyens plus efficaces d'utiliser votre composant.
Lorsque vous écrivez des erreurs et des avertissements, donnez des liens vers votre documentation ou montrez des exemples de code simples. Plus le développeur comprend rapidement quel est le problème et comment le résoudre, plus votre composant sera pratique pour le travail.
Incroyablement, mais il s'est avéré que la présence de tous ces longs avertissements d'erreur n'affecte pas la taille du package final. Grâce aux miracles de l'élimination du code mort, tous ces textes et codes d'erreur peuvent être supprimés lors de l'assemblage en production.
React lui-même est l'une des bibliothèques qui donne des commentaires incroyablement bons. Peu importe si vous avez oublié de spécifier la clé des éléments de la liste, ou si vous avez mal écrit la méthode du cycle de vie, ou peut-être avez-vous oublié d'étendre la classe de base ou d'appeler le crochet de manière incertaine - dans tous les cas, vous obtiendrez de gros messages d'erreur épais dans la console. Pourquoi les développeurs qui utilisent vos composants devraient-ils en attendre moins de vous?
Concevez donc pour vos futurs utilisateurs. Concevez vous-même à partir du futur. Design pour les malheureux qui devront maintenir votre code lors de votre départ! Conception pour les développeurs.
Total
Nous pouvons apprendre beaucoup de l'approche API classique. En suivant les conseils, astuces, règles et commandements de cet article, vous pouvez créer des composants faciles à utiliser, faciles à entretenir, intuitifs et, si nécessaire, très flexibles.