Composants composés en réaction

Publié: 2022-03-10
Résumé rapide ↬ Un composant composé est l'un des modèles avancés de React qui utilise un moyen intéressant de communiquer la relation entre les composants de l'interface utilisateur et de partager l'état implicite en tirant parti d'une relation parent-enfant explicite.

Les composants composés aident les développeurs à créer des API plus expressives et flexibles pour partager l'état et la logique au sein des composants. Ce didacticiel explique comment cela peut être réalisé à l'aide de l'API de contexte et de React pour créer des composants à l'aide de ce modèle avancé.

Remarque : Afin de pouvoir suivre, vous aurez besoin d'une compréhension de base de React et du fonctionnement de l'API Context.

Qu'est-ce qu'un composant composé ?

Les composants composés peuvent être considérés comme un modèle qui contient l'état et le comportement d'un groupe de composants, mais qui redonne toujours le contrôle du rendu de ses parties variables à l'utilisateur externe.

A partir de la définition ci-dessus, en prenant note des mots clés : état et comportement . Cela nous aide à comprendre que le composant composé traite de l'état (c'est-à-dire comment l'état se comporte dans un composant qui est entouré par un utilisateur externe étant le parent du composant).

L'objectif des composants composés est de fournir une API plus expressive et flexible pour la communication entre les composants parent et enfant.

Pensez-y comme les balises <select> et <option> en HTML :

 <select> <option value="volvo">Volvo</option> <option value="mercedes">Mercedes</option> <option value="audi">Audi</option> </select>

La balise select fonctionne avec la balise option qui est utilisée pour un menu déroulant pour sélectionner des éléments en HTML. Ici, le <select> gère l'état de l'interface utilisateur, puis les éléments <option> sont configurés sur la façon dont le <select> doit fonctionner. Les composants composés dans React sont utilisés pour créer un composant d'interface utilisateur déclaratif qui permet d'éviter le forage d'accessoires.

Le forage d'accessoires consiste à transmettre des accessoires à plusieurs composants enfants. C'est aussi ce qu'ils appellent une "odeur de code". Le pire aspect du forage d'accessoires étant que lorsque le composant parent est restitué, les composants enfants seront également restitués et provoqueront un effet domino sur le composant. Une bonne solution serait d'utiliser l'API React Context que nous examinerons également plus tard.

Plus après saut! Continuez à lire ci-dessous ↓

Application de composants composés dans React

Cette section explique les packages que nous pouvons utiliser dans notre application qui adoptent le modèle de composant composé des composants de construction dans React. Cet exemple est un composant Menu du package d'interface utilisateur @reach .

 import { Menu, MenuList, MenuButton, MenuItem, MenuItems, MenuPopover, MenuLink, } from "@reach/menu-button"; import "@reach/menu-button/styles.css";

Voici comment utiliser le composant Menu :

 function Example() { return ( <Menu> <MenuButton>Actions</MenuButton> <MenuList> <MenuItem>Download</MenuItem> <MenuLink to="view">View</MenuLink> </MenuList> </Menu> ); }

L'exemple de code ci-dessus est l'une des implémentations de composants composés dans laquelle vous pouvez voir que Menu , MenuButton , MenuList , MenuItem et MenuLink ont ​​tous été importés de @reach/menu-button . Au lieu d'exporter un seul composant, ReachUI exporte un composant parent qui est Menu accompagnant ses composants enfants qui sont MenuButton , MenuList , MenuItem et MenuLink .

Quand devriez-vous utiliser des composants composés ?

En tant que développeur React, vous devez utiliser des composants composés lorsque vous souhaitez :

  • Résoudre les problèmes liés à la construction de composants réutilisables ;
  • Développement de composants hautement cohésifs avec un couplage minimal ;
  • Meilleures façons de partager la logique entre les composants.

Avantages et inconvénients des composants composés

Un composant composé est un modèle React génial à ajouter à votre boîte à outils de développeur React. Dans cette section, j'exposerai les avantages et les inconvénients de l'utilisation de composants composés et ce que j'ai appris en construisant des composants à l'aide de ce modèle de développement.

Avantages

  • Séparation de préoccupation
    Avoir toute la logique d'état de l'interface utilisateur dans le composant parent et la communiquer en interne à tous les composants enfants permet une répartition claire des responsabilités.

  • Complexité réduite
    Contrairement au forage d'accessoires pour transmettre des propriétés à leurs composants spécifiques, les accessoires enfants vont à leurs composants enfants respectifs en utilisant le modèle de composant composé.

Les inconvénients

L'un des principaux inconvénients de la construction de composants dans React avec le modèle de composant composé est que seuls direct children du composant parent auront accès aux accessoires, ce qui signifie que nous ne pouvons pas envelopper l'un de ces composants dans un autre composant.

 export default function FlyoutMenu() { return ( <FlyOut> {/* This breaks */} <div> <FlyOut.Toggle /> <FlyOut.List> <FlyOut.Item>Edit</FlyOut.Item> <FlyOut.Item>Delete</FlyOut.Item> </FlyOut.List> </div> </FlyOut> ); }

Une solution à ce problème consisterait à utiliser le modèle de composant composé flexible pour partager implicitement l'état à l'aide de l'API React.createContext .

L'API de contexte permet de transmettre l'état React à travers des composants imbriqués lors de la construction à l'aide du modèle de composant composé des composants de construction dans React. Cela est possible car le context fournit un moyen de transmettre des données dans l'arborescence des composants sans avoir à transmettre manuellement des accessoires à chaque niveau. L'utilisation de l'API Context offre une grande flexibilité à l'utilisateur final.

Maintenir les composants composés dans React

Les composants composés offrent un moyen plus flexible de partager l'état dans les applications React, donc l'utilisation de composants composés dans vos applications React facilite la maintenance et le débogage de vos applications.

Construire une démo

Dans cet article, nous allons créer un composant accordéon dans React en utilisant le modèle de composants composés. Le composant que nous allons créer dans ce didacticiel serait un composant d'accordéon personnalisé, flexible et partageant l'état au sein du composant à l'aide de l'API de contexte.

Allons-y!

Tout d'abord, créons une application React en utilisant ce qui suit :

 npx create-react-app accordionComponent cd accordionComponent npm start

ou

 yarn create react-app accordionComponent cd accordionComponent yarn start

Les commandes ci-dessus créent une application React, remplacent le répertoire par le projet React et démarrent le serveur de développement.

Remarque : Dans ce didacticiel, nous utiliserons des styled-components de style pour aider à styliser nos composants.

Utilisez la commande ci-dessous pour installer styled-components :

 yarn add styled-components

ou

 npm install --save styled-components

Dans le dossier src , créez un nouveau dossier appelé components . C'est là que vivraient tous nos composants. Dans le dossier des composants , créez deux nouveaux fichiers : accordion.js et accordion.styles.js .

Le fichier accordion.styles.js contient notre style pour le composant Accordion (notre style a été fait à l'aide styled-components ).

 import styled from "styled-components"; export const Container = styled.div` display: flex; border-bottom: 8px solid #222; `;

Ci-dessus, un exemple de composants de style utilisant la bibliothèque css-in-js appelée styled-components .

Dans le fichier accordion.styles.js , ajoutez les styles restants :

 export const Frame = styled.div` margin-bottom: 40px; `; export const Inner = styled.div` display: flex; padding: 70px 45px; flex-direction: column; max-width: 815px; margin: auto; `; export const Title = styled.h1` font-size: 40px; line-height: 1.1; margin-top: 0; margin-bottom: 8px; color: black; text-align: center; `; export const Item = styled.div` color: white; margin: auto; margin-bottom: 10px; max-width: 728px; width: 100%; &:first-of-type { margin-top: 3em; } &:last-of-type { margin-bottom: 0; } `; export const Header = styled.div` display: flex; flex-direction: space-between; cursor: pointer; margin-bottom: 1px; font-size: 26px; font-weight: normal; background: #303030; padding: 0.8em 1.2em 0.8em 1.2em; user-select: none; align-items: center; img { filter: brightness(0) invert(1); width: 24px; user-select: none; @media (max-width: 600px) { width: 16px; } } `; export const Body = styled.div` font-size: 26px; font-weight: normal; line-height: normal; background: #303030; white-space: pre-wrap; user-select: none; overflow: hidden; &.closed { max-height: 0; overflow: hidden; transition: max-height 0.25ms cubic-bezier(0.5, 0, 0.1, 1); } &.open { max-height: 0px; transition: max-height 0.25ms cubic-bezier(0.5, 0, 0.1, 1); } span { display: block; padding: 0.8em 2.2em 0.8em 1.2em; } `;

Commençons à construire notre composant accordéon. Dans le fichier accordion.js , ajoutons le code suivant :

 import React, { useState, useContext, createContext } from "react"; import { Container, Inner, Item, Body, Frame, Title, Header } from "./accordion.styles";

Ci-dessus, nous importons les useState , useContext et createContext qui nous aideront à construire notre composant accordéon à l'aide de composants composés.

La documentation React explique que le context aide à fournir un moyen de transmettre des données à travers l'arborescence des composants sans avoir à transmettre manuellement les accessoires à tous les niveaux.

En regardant ce que nous avons importé plus tôt dans notre fichier accordion.js , vous remarquerez que nous avons également importé nos styles en tant que composants, ce qui nous aidera à créer nos composants plus rapidement.

Nous allons continuer et créer notre contexte pour le composant qui partagera les données avec les composants qui en ont besoin :

 const ToggleContext = createContext(); export default function Accordion({ children, ...restProps }) { return ( <Container {...restProps}> <Inner>{children}</Inner> </Container> ); }

Les composants Container et Inner de l'extrait de code ci-dessus proviennent de notre fichier ./accordion.styles.js dans lequel nous avons créé des styles pour nos composants à l'aide des composants styled-components (de la bibliothèque css-in-js ). Le composant Container abrite l'ensemble de l' Accordion que nous construisons en utilisant des composants composés.

Ici, nous créons un objet de contexte à l'aide de la méthode createContext() , donc lorsque React rend un composant qui s'abonne à cet objet Context, il lira la valeur de contexte actuelle du fournisseur correspondant le plus proche au-dessus de lui dans l'arborescence.

Ensuite, nous créons également notre composant de base qui est l'accordéon ; il faut les children et tout restProps . C'est notre composant parent qui abrite les composants enfants de l'accordéon.

Créons d'autres composants enfants dans le fichier accordion.js :

 Accordion.Title = function AccordionTitle({ children, ...restProps }) { return <Title {...restProps}>{children}</Title>; }; Accordion.Frame = function AccordionFrame({ children, ...restProps }) { return <Frame {...restProps}>{children}</Frame>; };

Remarquez le . après le composant Accordion parent ; ceci est utilisé pour connecter le composant enfant à son composant parent.

Nous allons continuer. Ajoutez maintenant ce qui suit au fichier accordion.js :

 Accordion.Item = function AccordionItem({ children, ...restProps }) { const [toggleShow, setToggleShow] = useState(true); return ( <ToggleContext.Provider value={{ toggleShow, setToggleShow }}> <Item {...restProps}>{children}</Item> </ToggleContext.Provider> ); }; Accordion.ItemHeader = function AccordionHeader({ children, ...restProps }) { const { isShown, toggleIsShown } = useContext(ToggleContext); return ( <Header onClick={() => toggleIsShown(!isShown)} {...restProps}> {children} </Header> ); }; Accordion.Body = function AccordionHeader({ children, ...restProps }) { const { isShown } = useContext(ToggleContext); return ( <Body className={isShown ? "open" : "close"}> <span>{children}</span> </Body> ); };

Nous créons donc ici un composant Body , Header et Item qui sont tous des enfants du composant parent Accordion . C'est là que cela pourrait commencer à devenir délicat. Notez également que chaque composant enfant créé ici reçoit également un accessoire children et restprops .

À partir du composant enfant Item , nous avons initialisé notre état à l'aide du hook useState et l'avons défini sur true. Ensuite, rappelez-vous également que nous avons créé un ToggleContext au niveau supérieur du fichier accordion.js qui est un Context Object , et lorsque React rend un composant qui s'abonne à cet objet Context, il lira la valeur de contexte actuelle du fournisseur correspondant le plus proche au-dessus. dans l'arbre.

Chaque objet Context est livré avec un composant Provider React qui permet aux composants consommateurs de s'abonner aux changements de contexte.

Le composant provider accepte une prop de value à transmettre aux composants consommateurs qui sont des descendants de ce fournisseur, et ici nous transmettons la valeur de l'état actuel qui est le toggleShow et la méthode pour définir la valeur de l'état actuel setToggleShow . Ils sont la valeur qui détermine comment notre objet de contexte partagera l'état autour de notre composant sans forage prop.

Ensuite, dans notre composant enfant d'en- header de l' Accordion , nous détruisons les valeurs de l'objet de contexte, puis modifions l'état actuel du toggleShow au clic. Donc, ce que nous essayons de faire, c'est de cacher ou d'afficher notre accordéon lorsque l'en-tête est cliqué.

Dans notre composant Accordion.Body , nous détruisons également le toggleShow qui est l'état actuel du composant, puis en fonction de la valeur de toggleShow , nous pouvons soit masquer le corps, soit afficher le contenu du composant Accordion.Body .

C'est donc tout pour notre fichier accordion.js .

C'est maintenant que nous voyons comment tout ce que nous avons appris sur les composants Context et Compound components se combinent. Mais avant cela, créons un nouveau fichier appelé data.json et collons-y le contenu ci-dessous :

 [ { "id": 1, "header": "What is Netflix?", "body": "Netflix is a streaming service that offers a wide variety of award-winning TV programs, films, anime, documentaries and more – on thousands of internet-connected devices.\n\nYou can watch as much as you want, whenever you want, without a single advert – all for one low monthly price. There's always something new to discover, and new TV programs and films are added every week!" }, { "id": 2, "header": "How much does Netflix cost?", "body": "Watch Netflix on your smartphone, tablet, smart TV, laptop or streaming device, all for one low fixed monthly fee. Plans start from £5.99 a month. No extra costs or contracts." }, { "id": 3, "header": "Where can I watch?", "body": "Watch anywhere, anytime, on an unlimited number of devices. Sign in with your Netflix account to watch instantly on the web at netflix.com from your personal computer or on any internet-connected device that offers the Netflix app, including smart TVs, smartphones, tablets, streaming media players and game consoles.\n\nYou can also download your favorite programs with the iOS, Android, or Windows 10 app. Use downloads to watch while you're on the go and without an internet connection. Take Netflix with you anywhere." }, { "id": 4, "header": "How do I cancel?", "body": "Netflix is flexible. There are no annoying contracts and no commitments. You can easily cancel your account online with two clicks. There are no cancellation fees – start or stop your account at any time." }, { "id": 5, "header": "What can I watch on Netflix?", "body": "Netflix has an extensive library of feature films, documentaries, TV programs, anime, award-winning Netflix originals, and more. Watch as much as you want, any time you want." } ]

Ce sont les données avec lesquelles nous allons travailler afin de tester notre composant accordéon.

Alors continuons. Nous avons presque terminé et je pense que vous avez beaucoup appris en suivant cet article.

Dans cette section, nous allons rassembler tout ce sur quoi nous avons travaillé et appris sur les composants composés pour pouvoir l'utiliser dans notre fichier App.js pour utiliser la fonction Array.map pour afficher les données que nous avons déjà sur le web page. Notez également qu'il n'y avait pas d'utilisation de state dans App.js ; tout ce que nous avons fait était de transmettre des données aux composants spécifiques et l'API Context s'est occupée de tout le reste.

Passons maintenant à la partie finale. Dans votre App.js , procédez comme suit :

 import React from "react"; import Accordion from "./components/Accordion"; import faqData from "./data"; export default function App() { return ( <Accordion> <Accordion.Title>Frequently Asked Questions</Accordion.Title> <Accordion.Frame> {faqData.map((item) => ( <Accordion.Item key={item.id}> <Accordion.Header>{item.header}</Accordion.Header> <Accordion.Body>{item.body}</Accordion.Body> </Accordion.Item> ))} </Accordion.Frame> </Accordion> ); }

Dans votre fichier App.js , nous avons importé notre accordéon de composant composé à partir du chemin du fichier, puis avons également importé nos données factices, mappées à travers les données factices afin d'obtenir les éléments individuels dans notre fichier de données, puis les avons affichés conformément à la respective composant, vous remarquerez également que tout ce que nous avions à faire était de transmettre les enfants au composant respectif, l'API Context s'occupe de s'assurer qu'il atteint le bon composant et qu'il n'y avait pas de forage d'accessoires.

Voici à quoi devrait ressembler notre produit final :

Aspect final de notre composant d'accordéon
Look final de notre composant d'accordéon. ( Grand aperçu )

Alternative aux composants composés

Une alternative à l'utilisation de composants composés serait d'utiliser l'API Render Props. Le terme Render Prop dans React fait référence à une technique de partage de code entre les composants React à l'aide d'un accessoire dont la valeur est une fonction. Un composant avec un accessoire de rendu prend une fonction qui renvoie un élément React et l'appelle au lieu d'implémenter sa propre logique de rendu.

Passer des données d'un composant à un composant enfant qui a besoin des données peut entraîner un forage d'accessoires lorsque vous avez des composants imbriqués les uns dans les autres. C'est l'avantage d'utiliser Context pour partager des données entre les composants plutôt que d'utiliser la méthode render prop.

Conclusion

Dans cet article, nous avons découvert l'un des modèles avancés de React qui est le modèle de composant composé. C'est une méthode géniale pour créer des composants réutilisables dans React en utilisant le modèle de composant composé pour créer votre composant, ce qui vous offre une grande flexibilité dans votre composant. Vous pouvez toujours choisir d'utiliser Render Prop si la flexibilité n'est pas ce dont votre composant a besoin pour le moment.

Les composants composés sont les plus utiles dans les systèmes de conception de bâtiments. Nous avons également suivi le processus de partage de l'état au sein des composants à l'aide de l'API Context.

  • Le code de ce tutoriel se trouve sur Codesandbox.