Comment éviter le forage avec composition

Photo par rawpixel sur Unsplash

React.js est l’un des frameworks front-end les plus populaires. C’est un excellent framework à base de composants avec une API déclarative qui permet au développeur de concevoir l’UI comme une fonction de l’état et des accessoires et non comme une fonction du temps. En d'autres termes, vous décrivez l'apparence de votre composant en fonction des données transmises.

Les données sont principalement transmises par les accessoires. Autrement dit, les accessoires sont les arguments des fonctions qui renvoient JSX. En fait, la forme la plus simple d'un composant est simplement cela: une fonction JavaScript.

const Header = props => {
    revenir(
         
            

{props.title}               ) }

Les accessoires peuvent être utilisés pour plusieurs choses dans le même composant. Dans l'exemple ci-dessus, nous l'utilisons pour configurer une classe CSS: dark ou light. Il est également utilisé pour fournir les données de la balise d’en-tête. Nous pouvons ensuite utiliser le composant en passant les accessoires comme attributs dans notre JSX, comme ceci:

const App = props => {
    revenir(
         
                           ) }

Comme vous pouvez le constater, les accessoires peuvent être très puissants. Cependant, s’ils sont mal appliqués, ils peuvent être très difficiles à gérer. L’un des plus gros «non» avec des accessoires est ce que l’on appelle «forage d’appui». Le forage d’appui consiste à transmettre un accessoire à un composant dans le seul but de le transmettre à un enfant.

const Parent = ({className, title}) => {
    revenir(
         
            {...}                            ) }

Dans l'exemple ci-dessus, le titre est transmis au parent, mais celui-ci ne l'utilise pas autrement que pour le transmettre au composant enfant. Ce n'est pas un moyen idéal pour transmettre des données. Supposons que notre composant enfant possède un autre accessoire dont nous devons tirer parti. Nous devons maintenant le transmettre à la composante parent pour le transmettre ensuite à l’enfant. Au fur et à mesure que le temps passe et que notre base de code grandit, plus nos données et nos composants sont sujets aux erreurs. (BTW, dans l'exemple ci-dessus, je profite d'un opérateur ES6 appelé déstructuration, sur lequel vous pouvez en apprendre davantage sur MDN)

Malgré le fait que nous sachions l’éviter, le forage à hélice s’insinue silencieusement sans même que nous le remarquions. Voici un exemple concret d'un projet sur lequel je travaillais. Je travaillais sur une section Hero qui avait un titre, un sous-titre et une liste de boutons ‘Call To Action’. C'est ce que j'ai commencé avec (je l'ai simplifié pour l'exemple pour le rendre plus facile à lire):

const Hero = ({titre, sous-titre, ctas}) => {
    revenir(
         
             {titre} 
             {sous-titre} 
            
               {ctas.map (cta => )}
            
         
    )
}

L'exemple ci-dessus prenait trois accessoires: titre, sous-titre et un tableau de cta (appel aux actions). Le titre et le sous-titre sont placés dans leurs composants correspondants, puis nous cartographions les ctas pour obtenir un tableau de LinkButtons. C'est assez simple à suivre et cela fonctionnait très bien.

Plus tard, je suis tombé sur la nécessité de disposer une rangée de LinkButtons ailleurs dans mon application. Heureusement, React facilite la réutilisation du code et j'ai remanié la rangée de boutons de mon composant Hero afin de pouvoir le réutiliser aux deux endroits. C'est ce que j'ai fini avec:

const ActionButtons = ({actions}) => {
    revenir(
       
          {actions.map (action => )}
       
    )
}
const Hero = ({titre, sous-titre, ctas}) => {
    revenir(
         
             {titre} 
             {sous-titre} 
            
         
    )
}

As-tu vu ce qui est arrivé? Je ne l’avais même pas remarqué au début. C’était si facile de refactoriser la partie dont j’avais besoin que je n’ai même pas remarqué que je venais de créer une situation de forage d’hélice pour moi-même. Je passais un accessoire Ctas dans le composant Hero uniquement pour me retourner et le transmettre à un autre composant. Cela aurait pu causer des maux de tête importants pour moi plus tard et tout ce que j'essayais de faire était de tirer parti de la réutilisation du code.

Heureusement, je me suis surpris et j'ai refactoré le code de cette façon:

const Hero = ({titre, sous-titre, enfants}) => {
    revenir(
         
             {titre} 
             {sous-titre} 
            {Enfants}
         
    )
}

   

Comme vous pouvez le constater, je ne rends plus explicitement le composant ActionButtons dans mon composant Hero. Je suis simplement en train de rendre l'accessoire aux enfants, disponible pour chaque composant de React. Ce modèle remet le contrôle dans la main des développeurs pour choisir quoi et si restituer quelque chose. Je passe ensuite le composant ActionButtons en tant qu'enfant au composant Hero. Cela me permet de transmettre directement les données au composant ActionButtons sans que le composant Hero n'ait même besoin de savoir quoi que ce soit à propos de l'API du composant ActionButtons.

Le mode de transmission des composants en tant qu’enfant s’appelle «Composition». C’est un modèle puissant qui permet à la fois le découplage des composants et la réutilisation du code. Si vous souhaitez en savoir plus sur la composition et son utilisation, je vous recommande de consulter la page de démarrage de React sur Composition vs Héritage.

L’avantage actuel de mon code est qu’au fur et à mesure que le composant ActionButtons s’améliore et qu’il change, le composant Hero n’a pas besoin de le savoir. Cela donnait également plus de flexibilité au composant Héros, car il n'était plus couplé au composant ActionButtons. Ainsi, il peut désormais restituer tout ce dont j'ai besoin ou rien du tout. Mon code sera beaucoup plus facile à gérer à mesure que ma base de code grandira.