React – Les Higher Order Components (HOC)
Dans le domaine constamment évolutif du développement web, la maîtrise des concepts avancés est essentielle pour créer des applications robustes et flexibles. Dans cet article, nous allons explorer l’un de ces concepts fondamentaux de React : les composants HOCs, plus communément appelés “Higher-Order Components”.
Que vous soyez un développeur chevronné en quête de techniques avancées ou un néophyte curieux d’apprendre, nous allons parcourir étape par étape la création et l’application des HOC. Préparez-vous à enrichir votre boîte à outils de développement avec cette approche puissante, tout en découvrant comment optimiser la lisibilité, la réutilisabilité et la maintenabilité de votre code.
Qu’est ce qu’un Higher Order Component ?
Imaginez que vous possedez une pâtisserie spécialisée dans la création d’une grande variété de pâtisseries, telles que des croissants, des muffins et des pains aux raisins. Chaque pâtisserie doit être étiquetée avec son type et ses ingrédients. Faire cela manuellement pour chaque pâtisserie demanderait énormément de temps, mais plutôt que de le faire à la main, vous pouvez utiliser un “robot” qui s’en chargera automatiquement.
Ce robot est en réalité un “Higher-Order Component” (HOC), une fonction qui prend un composant (ta pâtisserie) en entrée et renvoie ce même composant avec des fonctionnalités ou des caractéristiques supplémentaires. Dans ce cas, il ajouterait un label indiquant le type et les ingrédients de la pâtisserie à chaque instance de pâtisserie.
Avantages
Les Higher-Order Components (HOC) offrent plusieurs avantages significatifs qui améliorent la manière dont nous développons nos applications React. Voici quelques-uns de ces avantages, accompagnés d’exemples concrets :
- Réutilisabilité : L’un des atouts majeurs des HOC est leur capacité à être réutilisés dans différentes parties de votre application. Puisqu’un HOC est une fonction avec une logique spécifique, vous pouvez le personnaliser en fonction de vos besoins tout en le gardant flexible. Par exemple, un HOC d’authentification pourrait être adapté pour gérer l’accès à différents types de contenus.
- Séparation des responsabilités : Au lieu d’encombrer un composant avec plusieurs logiques distinctes, les HOC permettent de séparer ces responsabilités en des composants distincts. Vous pouvez facilement imaginer la création d’un HOC distinct pour chaque logique, rendant ainsi vos composants plus clairs et mieux organisés.
- Modularité du code : Les HOCs ajoutent une couche modulaire à votre code. Vous pouvez ajouter ou supprimer un HOC sans affecter le fonctionnement du composant sous-jacent, ce qui facilite la maintenance et l’adaptation de votre application. En somme, les HOC s’imbriquent sans altérer la stabilité globale.
- Facilitation des tests unitaires : Grâce à leur nature isolée, les HOC simplifient les tests unitaires. Vous pouvez tester la logique spécifique d’un HOC sans la complexité d’autres parties de l’application.
En combinant ces avantages, vous serez en mesure de créer des applications plus flexibles et plus maintenables tout en minimisant la duplication de code.
Cas pratique
Problématique
Prenons un exemple concret pour illustrer la pertinence des Higher-Order Components. Supposons que nous développons une application avec un système d’authentification. Dans cette application, différentes parties de l’interface requièrent une authentification :
- Page d’accueil : Cette page ne nécessite pas d’authentification.
- Liste des livres : Cette liste peut être consultée sans authentification.
- Les livres du moment : Cette section est réservée aux utilisateurs authentifiés.
- Avis des utilisateurs : De même, seuls les utilisateurs connectés peuvent voir les avis.
Imaginons que nous avons un composant qui import tous les autres :
export const App = () => {
return (
<div>
<Home />
<BooksList />
<TopBook />
<UsersRating />
</div>
)
}
Maintenant imaginons un composant par partie :
export const Home = () => {
return (
<div>
<h1>Hey !</h1>
<p>Ceci est un message de bienvenue</p>
</div>
)
}
export const BooksList = () => {
return (
<div>
<p>Books list</p>
</div>
)
}
export const TopBook = () => {
const isConnected = false
if(!isConnected) {
return (
<p>You don't have access !</p>
)
}
return (
<div>
<p>Top Book</p>
</div>
)
}
export const UsersRating = () => {
const isConnected = false
if(!isConnected) {
return (
<p>You don't have access !</p>
)
}
return (
<div>
<p>UsersRating</p>
</div>
)
}
On remarque que les deux composants ayant la logique de restriction repète le même code. Ce n’est pas très grave dans notre cas car nous avons que deux composants, mais imaginons que nous avons 10 composants, cela fait beaucoup de répétition de code…
Face à ce scénario, il est important de trouver une solution qui gère l’affichage conditionnel des contenus en fonction de l’état d’authentification. C’est là qu’interviennent les Higher-Order Components (HOC).
Solution : Les Higher Order Components !
Pour résoudre ce problème de répétition de code à plusieurs endroits, nous allons isoler la logique d’authentification dans un HOC que nous nommerons withAuthentication
:
export const withAuthentication = (Component) => {
const isConnected = false
if (!isConnected) {
return <p>You don't have access !</p>
}
return (props) => <Component {...props} />
}
Ensuite, nous allons appliquer ce HOC sur les composants qui nécessitent une restriction d’accès, comme ceci :
export const TopBook = withAuthentication(() => {
return (
<div>
<p>Top Book</p>
</div>
)
})
export const UsersRating = withAuthentication(() => {
return (
<div>
<p>UsersRating</p>
</div>
)
})
En imaginant que le isConnected vous le récupéré soit d’un props, soit d’un contexte, nous avons une logique isolé et réutilisable.
Aller plus loin
Nous pouvons aller plus loin avec les HOCs. Imaginons maintenant que nous voulons faire de la mise en page :
export const Profile = () => {
// This is the beta version of Profile
return (
<div>
<p>Beta Profile</p>
<h1>Nicolas BROUARD<h1>
</div>
)
}
Nous avons notre vue Profile et nous voulons lui ajouter un bandeau “Beta” pour avertir qu’il s’agit bien ici de la version Beta du profil. Nous pouvons aussi utiliser un HOC :
export const withBetaBanner = (Component) => {
return (props) => (
<>
<header className="beta-header">This is a beta version</header>
<Component {...props} />
</>
)
}
Vous pouvez très bien toucher aux props aussi si nécessaire. Les HOCs sont très puissants !
Conclusion
En conclusion, vous avez maintenant toutes les clés en main pour exploiter pleinement la puissance des Higher-Order Components (HOCs) dans vos projets React.
En combinant des concepts tels que la transmission de props, la composition de HOC et l’utilisation de Typescript pour la sécurité du typage, vous pouvez désormais créer des composants plus flexibles, plus propres et plus efficaces. Les HOCs offrent une approche pratique pour gérer des préoccupations transversales et simplifier vos composants, ce qui peut grandement faciliter la maintenance et l’extension de vos applications.
Continuez à expérimenter avec les HOCs dans vos projets, et n’hésitez pas à explorer des exemples concrets pour approfondir votre compréhension. En maîtrisant l’art des HOC, vous aurez un atout de taille pour créer des applications React robustes et évolutives. Alors, lancez-vous, appliquez ces connaissances et transformez vos composants en blocs de construction flexibles et puissants pour vos futures créations React.