Cet article vous donne principalement une compréhension approfondie des composants d'ordre supérieur de React. J'espère que vous aurez une compréhension plus claire des composants d'ordre supérieur de React.
1. Dans React, le composant d'ordre supérieur (HOC) est une technologie avancée pour réutiliser la logique des composants. HOC ne fait pas partie de l'API React. Un HOC est une fonction qui prend un composant et renvoie un nouveau composant. Dans React, les composants constituent l’unité de base de la réutilisation du code.
2. Pour expliquer les HOC, prenons les deux exemples suivants
Le composant CommentList affichera une liste de commentaires et les données de la liste proviennent de l'extérieur.
class CommentList extends React.Component { constructor() { super(); this.handleChange = this.handleChange.bind(this); this.state = { // "DataSource" is some global data source comments: DataSource.getComments() }; } componentDidMount() { // Subscribe to changes DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { // Clean up listener DataSource.removeChangeListener(this.handleChange); } handleChange() { // Update component state whenever the data source changes this.setState({ comments: DataSource.getComments() }); } render() { return ( <p> {this.state.comments.map((comment) => ( <Comment comment={comment} key={comment.id} /> ))} </p> ); } }
Vient ensuite le composant BlogPost, qui est utilisé pour afficher un message de blog
class BlogPost extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { blogPost: DataSource.getBlogPost(props.id) }; } componentDidMount() { DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { DataSource.removeChangeListener(this.handleChange); } handleChange() { this.setState({ blogPost: DataSource.getBlogPost(this.props.id) }); } render() { return <TextBlock text={this.state.blogPost} />; } }
Les deux composants sont différents. Ils appellent des méthodes différentes de DataSource. également différent, mais la plupart de leurs implémentations sont les mêmes :
1 Une fois le chargement terminé, un écouteur de changement est ajouté au DataSource
2. Lorsque la source de données change, appelez setState
. à l'intérieur de l'écouteur 3. Après la désinstallation, supprimez le changement d'écouteur
Il est concevable que dans les grandes applications, le même modèle d'accès à DataSource et d'appel de setState se reproduise encore et encore. Nous souhaitons faire abstraction de ce processus afin de définir cette logique uniquement en un seul endroit, puis de la partager entre plusieurs composants.
Ensuite, nous écrivons une fonction qui crée un composant. Cette fonction accepte deux paramètres, dont l'un est le composant et l'autre est la fonction. La fonction withSubscription est appelée ci-dessous
const CommentListWithSubscription = withSubscription( CommentList, (DataSource) => DataSource.getComments() ); const BlogPostWithSubscription = withSubscription( BlogPost, (DataSource, props) => DataSource.getBlogPost(props.id) );
Le premier paramètre transmis lors de l'appel de withSubscription est le composant encapsulé, et le deuxième paramètre est une fonction utilisée pour récupérer des données.
Lorsque CommentListWithSubscription et BlogPostWithSubscription sont rendus, CommentList et BlogPost accepteront un accessoire appelé data, qui stocke les données actuellement récupérées de DataSource. Le code withSubscription est le suivant :
// This function takes a component... function withSubscription(WrappedComponent, selectData) { // ...and returns another component... return class extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { data: selectData(DataSource, props) }; } componentDidMount() { // ... that takes care of the subscription... DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { DataSource.removeChangeListener(this.handleChange); } handleChange() { this.setState({ data: selectData(DataSource, this.props) }); } render() { // ... and renders the wrapped component with the fresh data! // Notice that we pass through any additional props return <WrappedComponent data={this.state.data} {...this.props} />; } }; }
HOC ne modifie pas le composant d'entrée et n'utilise pas non plus l'héritage pour réutiliser son comportement. HOC n'est qu'une fonction. Le composant encapsulé accepte tous les accessoires du conteneur, ainsi qu'un nouveau accessoire (données), qui est utilisé pour restituer la sortie du composant encapsulé. HOC ne se soucie pas de la manière dont les données sont utilisées ni de la raison pour laquelle elles sont utilisées, et le composant encapsulé ne se soucie pas de l'endroit où les données sont obtenues.
Étant donné que withSubscription n'est qu'une fonction normale, vous pouvez ajouter n'importe quel nombre de paramètres. Par exemple, vous pouvez rendre le nom du accessoire de données configurable pour isoler davantage le HOC du composant encapsulé.
Soit acceptez une configuration ShouldComponentUpdate, soit configurez les paramètres de la source de données
Il y a certaines choses auxquelles il faut prêter attention lors de l'utilisation de composants d'ordre élevé.
1. Ne modifiez pas le composant d'origine, c'est très important
Il y a les exemples suivants :
function logProps(InputComponent) { InputComponent.prototype.componentWillReceiveProps = function(nextProps) { console.log('Current props: ', this.props); console.log('Next props: ', nextProps); }; // The fact that we're returning the original input is a hint that it has // been mutated. return InputComponent; } // EnhancedComponent will log whenever props are received const EnhancedComponent = logProps(InputComponent);
Il y a quelques problèmes ici, 1. L'entrée Le composant ne peut pas être comparé à celui amélioré. Les composants sont réutilisés individuellement. 2. Si vous appliquez d'autres HOC à EnhancedComponent, composantWillReceiveProps sera également modifié.
Ce HOC ne s'applique pas aux composants de type fonction, car les composants de type fonction n'ont pas de cycle de vie. La fonction HOC doit utiliser la composition au lieu de la modification - en encapsulant le composant d'entrée dans un composant conteneur.
function logProps(WrappedComponent) { return class extends React.Component { componentWillReceiveProps(nextProps) { console.log('Current props: ', this.props); console.log('Next props: ', nextProps); } render() { // Wraps the input component in a container, without mutating it. Good! return <WrappedComponent {...this.props} />; } } }
Ce nouveau logProps a les mêmes fonctionnalités que l'ancien logProps, tandis que le nouveau logProps évite les conflits potentiels. Il en va de même pour les composants de type classe et les composants de type fonction.
2. N'utilisez pas de HOC dans la méthode de rendu
L'algorithme diff de React utilise l'identité du composant pour décider s'il doit mettre à jour le sous-arbre existant ou détruire l'ancien sous-arbre et charger un new , si le composant renvoyé par la méthode de rendu est égal au composant précédemment rendu (===), alors React mettra à jour le composant précédemment rendu via l'algorithme diff. Sinon, le sous-arbre précédemment rendu sera complètement déchargé.
render() { // A new version of EnhancedComponent is created on every render // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); // That causes the entire subtree to unmount/remount each time! return <EnhancedComponent />; }
Utilisez les HOC en dehors de la définition du composant afin que le composant résultant ne soit créé qu'une seule fois. Dans quelques cas, vous devez appliquer les HOC de manière dynamique, vous devez le faire dans la fonction de cycle de vie ou le constructeur
3 Les méthodes statiques doivent être copiées manuellement
Parfois dans React, c'est très utile. pour définir des méthodes statiques sur les composants. Lorsque vous appliquez des HOC à un composant, bien que le composant d'origine soit enveloppé dans un composant conteneur, le nouveau composant renvoyé n'aura aucune méthode statique du composant d'origine.
// Define a static method WrappedComponent.staticMethod = function() {/*...*/} // Now apply an HOC const EnhancedComponent = enhance(WrappedComponent); // The enhanced component has no static method typeof EnhancedComponent.staticMethod === 'undefined' // true
Pour que le composant renvoyé ait les méthodes statiques du composant d'origine, il est nécessaire de copier les méthodes statiques du composant d'origine vers le nouveau composant à l'intérieur de la fonction.
function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} // Must know exactly which method(s) to copy :( // 你也能够借助第三方工具 Enhance.staticMethod = WrappedComponent.staticMethod; return Enhance; }
4. La référence sur le composant conteneur ne sera pas transmise au composant enveloppé
Bien que les accessoires sur le composant conteneur puissent être facilement transmis au composant encapsulé, mais la référence sur le composant conteneur n'est pas transmise au composant encapsulé. Si vous définissez une référence pour un composant renvoyé via HOC, cette référence fait référence au composant conteneur le plus externe, et non au composant encapsulé.
Recommandations associées
Partage d'exemples d'entrée de composant d'ordre supérieur React
Comment utiliser le composant d'ordre supérieur Vue
Utilisez un exemple très simple pour comprendre l'idée des composants d'ordre supérieur de React.js
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!