Les composants React sont magiques et extrêmement flexibles. Nous pouvons jouer avec de nombreuses astuces dans la conception des composants. Mais il est très important de garantir le principe de responsabilité unique du composant : cela peut rendre nos composants plus simples et plus pratiques à entretenir, et plus important encore, cela peut rendre les composants plus réutilisables. Cet article partage principalement avec vous plusieurs méthodes avancées de décomposition des composants React, dans l'espoir de vous aider.
Cependant, comment décomposer un composant React complexe et volumineux n'est peut-être pas une tâche simple. Cet article présente trois méthodes de décomposition des composants React du moins profond au plus profond.
C'est la méthode la plus simple à laquelle penser : lorsqu'un composant restitue plusieurs éléments, vous devez essayer de séparer la logique de rendu de ces éléments. Le moyen le plus rapide consiste à diviser la méthode render() en plusieurs méthodes de sous-rendu.
Ce sera plus intuitif si vous regardez l'exemple suivant :
class Panel extends React.Component { renderHeading() { // ... } renderBody() { // ... } render() { return ( <div> {this.renderHeading()} {this.renderBody()} </div> ); } }
Les lecteurs attentifs découvriront rapidement que cela ne décompose pas réellement le composant lui-même. Le composant Panel conserve toujours son original. état. accessoires et méthodes de classe.
Comment réduire réellement la complexité des composants ? Nous devons créer des sous-composants. À l'heure actuelle, ce sera certainement une bonne tentative d'adopter des composants fonctionnels/composants apatrides pris en charge et recommandés par la dernière version de React :
const PanelHeader = (props) => ( // ...);const PanelBody = (props) => ( // ...);class Panel extends React.Component { render() { return ( <div> // Nice and explicit about which props are used <PanelHeader title={this.props.title}/> <PanelBody content={this.props.content}/> </div> ); } }
Par rapport à la méthode précédente, cette subtile amélioration est révolutionnaire.
Nous avons créé deux nouveaux composants unitaires : PanelHeader et PanelBody. Cela facilite les tests et nous pouvons tester directement différents composants séparément. Dans le même temps, avec l'aide du nouveau moteur algorithmique de React, React Fiber, l'efficacité du rendu des deux composants unitaires devrait, avec optimisme, être considérablement améliorée.
Retour au point de départ du problème, pourquoi un composant devient-il gonflé et compliqué ? L'une est qu'il existe de nombreux éléments de rendu imbriqués, et l'autre est qu'il existe de nombreux changements au sein du composant, ou qu'il existe plusieurs configurations.
À ce stade, nous pouvons transformer le composant en modèle : le composant parent est similaire à un modèle et se concentre uniquement sur diverses configurations.
Permettez-moi de donner un exemple pour que ce soit plus clair à comprendre.
Par exemple, nous avons un composant Commentaire, qui a plusieurs comportements ou événements.
Parallèlement, les informations affichées par le composant changent en fonction de l'identité de l'utilisateur :
Si l'utilisateur est l'auteur de ce commentaire ; 🎜>
À l'heure actuelle, au lieu de confondre toute la logique, une meilleure approche consiste peut-être à utiliser React pour transférer les caractéristiques de l'élément React entre les composants, afin qu'il ressemble davantage à un modèle puissant. . :
À ce stade, notre véritable composant Commentaire est organisé comme :class CommentTemplate extends React.Component { static propTypes = { // Declare slots as type node metadata: PropTypes.node, actions: PropTypes.node, }; render() { return ( <div> <CommentHeading> <Avatar user={...}/> // Slot for metadata <span>{this.props.metadata}</span> </CommentHeading> <CommentBody/> <CommentFooter> <Timestamp time={...}/> // Slot for actions <span>{this.props.actions}</span> </CommentFooter> </div> ... ) } }
class Comment extends React.Component { render() { const metadata = this.props.publishTime ? <PublishTime time={this.props.publishTime} /> : <span>Saving...</span>; const actions = []; if (this.props.isSignedIn) { actions.push(<LikeAction />); actions.push(<ReplyAction />); } if (this.props.isAuthor) { actions.push(<DeleteAction />); } return <CommentTemplate metadata={metadata} actions={actions} />; } }
Par exemple :
S'il s'agit de l'auteur lui-même, le contenu à restituer doit être ajouté avec
Méthode 3 : Composants d'ordre élevé
Une approche courante consiste à ajouter une logique de code aux fonctions de cycle de vie ComponentDidMount et ComponentWillUnmount du composant Document :
Quelques problèmes liés à cette opération sont :class Document extends React.Component { componentDidMount() { ReactDOM.findDOMNode(this).addEventListener('click', this.onClick); } componentWillUnmount() { ReactDOM.findDOMNode(this).removeEventListener('click', this.onClick); } onClick = (e) => { // Naive check for <a> elements if (e.target.tagName === 'A') { sendAnalytics('link clicked', { // Specific information to be sent documentId: this.props.documentId }); } }; render() { // ... } }
En plus de sa logique principale : affichant la page principale, le composant associé Document a une autre logique statistique
S'il y a une autre logique dans la fonction de cycle de vie de ; le composant Document, alors ce composant deviendra plus ambigu et déraisonnable ;
le code logique statistique ne peut pas être réutilisé
La reconstruction et la maintenance des composants seront le changement est plus difficile.
Pour résoudre ce problème, nous avons proposé le concept de composants d'ordre supérieur : les composants d'ordre supérieur (HOC). Sans expliquer ce terme de manière obscure, regardons directement comment refactoriser le code ci-dessus en utilisant des composants d'ordre supérieur :
function withLinkAnalytics(mapPropsToData, WrappedComponent) { class LinkAnalyticsWrapper extends React.Component { componentDidMount() { ReactDOM.findDOMNode(this).addEventListener('click', this.onClick); } componentWillUnmount() { ReactDOM.findDOMNode(this).removeEventListener('click', this.onClick); } onClick = (e) => { // Naive check for <a> elements if (e.target.tagName === 'A') { const data = mapPropsToData ? mapPropsToData(this.props) : {}; sendAnalytics('link clicked', data); } }; render() { // Simply render the WrappedComponent with all props return <WrappedComponent {...this.props} />; } } ... }
L'existence de composants d'ordre élevé démontre parfaitement les capacités de composition innées de React. Dans la communauté React, réagissez-redux, styled-components, réagissez-intl, etc. ont généralement adopté cette approche. Il convient de mentionner que la bibliothèque de classes de recomposition utilise des composants d'ordre élevé et les transmet pour réaliser des choses « d'expansion cérébrale ».
La montée en puissance de React et de ses communautés environnantes a rendu la programmation fonctionnelle populaire et populaire. Je pense que les idées sur la décomposition et la composition valent la peine d'être apprises. Dans le même temps, une suggestion pour le développement et la conception est que, dans des circonstances normales, n'hésitez pas à diviser vos composants en composants plus petits et plus simples, car cela peut conduire à la robustesse et à la réutilisation.
Recommandations associées :
Exemple d'analyse du cycle de vie des composants React
La méthode la plus complète pour créer des composants React
Explication détaillée de la façon dont le magasin optimise les composants React
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!