
Cet article sera principalement utile aux développeurs qui ne travaillent pas avec des ensembles de composants prêts à l'emploi, tels que material-ui, mais implémentent les leurs. Par exemple, un design a été développé pour un produit qui reflète à quoi devraient ressembler les boutons, les fenêtres modales, etc. Pour implémenter correctement un tel système de conception, tous ses atomes devront ajouter un bon support pour leur composition. En d'autres termes, il est nécessaire de s'assurer que tout composant unique peut s'intégrer et s'intégrer parfaitement dans un composant composite plus grand. Et s'il ne rentre pas, ce serait bien d'avoir un support simple pour sa personnalisation. Quoi qu'il en soit, il s'agit d'un grand sujet distinct, et j'y reviendrai peut-être une autre fois.
Paroles
Bonjour à tous. Je commence mon voyage sur le hub par un article simple mais utile. Quant à moi, cela s'est avéré trop détaillé, mais j'ai quand même essayé de m'adapter au lecteur, et non à moi-même. Avant d'écrire le prochain article (s'il y en a un) sur un sujet plus complexe, j'ai envie d'ajuster ma présentation sur le feedback (s'il y en a un).
Termes utilisés:
- Un composant visuel est un composant qui renvoie un élément incorporé dans le DOM. Par exemple,
return (<div />)
. Un composant qui renvoie uniquement un autre composant ne doit pas être interprété visuellement.
Présentation
Lorsque vous développez un composant, vous ne pouvez pas le rendre totalement universel. Dans votre tête, vous partez toujours d'options spécifiques pour son utilisation. Il s'avère souvent qu'après le développement, vos collègues commencent à "pousser ce composant n'importe où". Vous êtes en colère contre eux: «Eh bien, je ne l'ai pas développé pour ça! Il n'est pas destiné à cette tâche! » Bien entendu, des améliorations sont inévitables, voire nécessaires. Mais cela ne devrait pas être des améliorations comme lancer de nouveaux accessoires pour augmenter le retrait de 4px à 8px, qui seront utilisés dans un ou deux cas sur cinquante. Les composants doivent avoir une géométrie externe personnalisée.
TypeScript, aidez
Considérez l'interface, qui dans le sens devrait être située, par exemple, dans
src/Library/Controls.ts
. De brefs commentaires sont donnés pour les champs, ci-dessous nous les analyserons plus en détail.
export interface VisualComponentProps {
Il s'agit de l'interface des accessoires des composants. Lesquels? Tous les composants visuels. Ils doivent être appliqués à son élément racine.
Les accessoires de chaque composant visuel développé doivent être développés à l'aide de cette interface.
Veuillez immédiatement faire attention au fait que tous ces accessoires sont facultatifs. Considérez-les.
children
sont dans les composants de la classe React.Component, les composants du composant React.FC, mais ils ne sont pas dans des fonctions ordinaires sans spécifier le typage React.FC. Par conséquent, nous lui demandons.className/style
utilisons des noms similaires, comme dans le JSX'nom <div /> habituel. Nous ne produisons pas de sémantique. Ce principe d'identité du nom est utilisé, par exemple, dans les accessoires pour spécifier le lien ref .doNotRender
utilisé comme une alternative à la béquille douloureuse dans le rendu JSX par condition . En appliquant cette solution, nous n'avons pas besoin de mettre d'accolades dans les méthodes de rendu, ce qui nuit à la lisibilité du code. Comparez 2 extraits de code:
Rendu conditionnel vierge:
App.tsx
renderComponent() { const {props, state} = this; const needRender = state.something; return ( <PageLayout> <UIButton children={'This is a button'} /> {needRender && <UIButton children={'This is another button'} /> } </PageLayout> ); }
Les accessoires du Tchad doNotRender:
App.tsx
renderComponent() { const {props, state} = this; const needRender = state.something; return ( <PageLayout> <UIButton children={'This is a button'} /> <UIButton children={'This is another button'} doNotRender={!needRender} /> </PageLayout> ); }
Dans la première version, nous augmentons le niveau d'imbrication du bouton du bas, bien qu'en termes de signification, son imbrication est au même niveau que celui du haut. Cela semble mauvais dans mon éditeur, où j'utilise un onglet d'une largeur de 2 espaces, et ici c'est encore pire.
Dans la deuxième option, nous avons une imbrication égale, moins que doNotRender peut ne pas attirer l'attention et le développeur ne comprendra pas ce qui se passe. Mais, si dans votre projet chaque composant visuel est réalisé selon ce principe, ce problème disparaît immédiatement.
fallback
nécessaire si nous ne voulons pas rendre null
avec doNotRender true
, mais une sorte d'élément personnalisé. Il est utilisé par analogie avec React Suspense , car il a une signification similaire (nous ne produisons pas de sémantique)
Je veux montrer comment l'utiliser correctement. Faisons un simple bouton.
Remarque: dans le code ci-dessous, j'utilise également des modules css, sass et classnames.
UIButton.tsx
import * as React from 'react'; import { VisualComponentProps } from 'Library/Controls'; import * as css from './Button.sass'; import cn from 'classnames';
App.tsx
renderComponent() { const {props, state} = this; const needRenderSecond = true; return ( <PageLayout> <UIButton children={'This is a button'} style={{marginRight: needRenderSecond ? 5 : null}} /> <UIButton disabled children={'This is another button'} doNotRender={!needRenderSecond} /> </PageLayout> ); }
Résultat:

Réflexion et conclusion
Il est commode de fonctionner avec des composants tels que les divs, créant divers wrappers, compositions, spécialisations,
allant au-delà du cadre de la fonctionnalité d'origine intégrée .
On peut faire valoir que, comme il n'y a pas de boutons jaunes conditionnels dans le système de conception et que le développeur doit les créer, le problème ne réside pas dans les composants, mais dans le fait que ce besoin crée. Cependant, la réalité est que de telles situations se produisent, et assez souvent. "... Mais nous devons vivre! Nous devons vivre." De plus, le principe de la cascade css ne peut pas toujours être mis en pratique, et vous pouvez rencontrer des cas où vos styles chevauchent simplement la spécificité plus élevée d'un autre sélecteur (ou décrit ci-dessus). Ici, le style aide.
Enfin, j'ajouterai quelques (littéralement) moments.
- Notez que doNotRender ne répète pas complètement le comportement de rendu conditionnel. Vous exécuterez également des méthodes de cycle de vie, juste le rendu renverra une solution de remplacement ou null. Dans certains composants complexes, vous souhaiterez peut-être éviter d'exécuter des méthodes de cycle de vie. Pour ce faire, il vous suffit de faire une spécialisation intégrée de votre composant.
En utilisant l'exemple UIButton: renommez le UIButton en UIButtonInner et ajoutez le code suivant en dessous:
UIButton.tsx
export function UIButton(props: ButtonProps) { if (props.doNotRender) return props.fallback || null; return <UIButtonInner {...props} />; }
PS Ne faites pas d'erreur d'appel récursif UIButton dans cette fonction!
- Dans de rares cas où les styles sur l'encapsuleur et sur le composant encapsulé peuvent changer indépendamment, l'interface suivante peut vous être utile
Library/Controls.ts
export interface VisualComponentWrapperProps extends VisualComponentProps { wrappedVisual?: VisualComponentProps; }
Et son utilisationUIButton.tsx
interface ButtonSomeWrapperProps extends ButtonBasicProps, VisualComponentWrapperProps { myCustomProp?: number; } export function UIButtonSomeWrapper(props: ButtonSomeWrapperProps) { if (props.doNotRender) return props.fallback || null; const {
Le développement d'une application utilisant cette approche augmentera considérablement la réutilisabilité de vos composants, réduira le nombre de styles de béquilles inutiles (en parlant des styles décrits dans les fichiers de style du composant exclusivement pour les besoins des autres composants) et des accessoires, et ajoutera du code structuré. C’est tout. Dans le prochain article, nous allons commencer à résoudre les problèmes de réutilisation des composants plus en termes de code qu'en CSS. Ou je vais écrire sur quelque chose de plus intéressant. Merci de votre attention.