1. Livres & vidéos
  2. React et TypeScript
  3. Créer ses premiers composants
Extrait - React et TypeScript Vers des applications web professionnelles
Extraits du livre
React et TypeScript Vers des applications web professionnelles Revenir à la page d'achat du livre

Créer ses premiers composants

La déclaration d’un premier composant

Les composants sont des briques réutilisables destinées à être affichées et qui permettent d’ordonner le code. Ils évitent ainsi la duplication de code, séparent les différentes fonctions et fonctionnalités, et permettent d’uniformiser l’interface utilisateur. Ils sont incontournables lors de la création d’applications en React (il est impossible de maintenir un code en React sans en utiliser). Toutefois le concept de composant dépasse de très loin, dans le domaine du développement front-end, le cadre du développement en React, et est utilisé dans de nombreuses bibliothèques front-end (Angular, SolidJS, Svelte, etc.). Ces connaissances peuvent donc ouvrir à l’apprentissage d’autres fraweworks et bibliothèques qui se basent sur ce concept.

React a connu de nombreuses évolutions depuis ses débuts. L’une des évolutions les plus conséquentes est la disparition progressive des composants en classe au profit des composants fonctionnels. Il convient de garder à l’esprit que certaines entreprises, lors des entretiens, peuvent poser des questions sur ce sujet quand bien même les composants en classe tombent en désuétude. Il existe en effet de nombreuses entreprises ayant une base de code en React avec...

Le transfert de données entre composants

Pour l’instant, ce composant n’est pas modulable : il affichera toujours la même chose. C’est ici qu’intervient le concept de prop. Pour que notre composant devienne modulable et qu’il n’affiche pas toujours la même valeur nous avons besoin d’y injecter des données. Par exemple, nous pourrions décider que notre composant affiche un nom d’utilisateur ainsi que son adresse électronique. Ces données sont ce qu’on appelle des props (propriétés). En matière de syntaxe à l’usage, elles sont très similaires aux attributs des balises HTML.

La philosophie de React repose sur une approche unidirectionnelle. C’est-à-dire que les données transitent des composants parents vers les composants enfants, mais il n’est pas possible de faire transiter des données des composants enfants vers les composants parents, seulement de manière indirecte via des fonctions de rappel. Cette approche distingue React d’autres bibliothèques, notamment Angular, qui, lui, se base sur du transfert de données bidirectionnel. Cela n’a pas d’impact en termes de performances, mais encourage certains patrons de développements au détriment d’autres.

1. La déclaration des props

Pour injecter des props dans un composant, la première étape est de typer notre composant en déclarant ses props avec le mot-clé TypeScript type ou avec le mot-clé interface. La documentation de TypeScript recommande l’usage du mot-clé interface, mais il est courant de retrouver les deux manières de déclarer dans le code des applications professionnelles. De même, les conventions de nommage varient d’un projet à l’autre. Mais ici, les types seront toujours déclarés en répétant le nom du composant accolé au mot Props, ce qui, pour MyComponent, donne MyComponentProps. Une fois le type déclaré, il doit être passé en paramètre à la fonction du composant et peut être utilisé comme un objet JavaScript.

Au sein du composant, les props ne peuvent pas être modifiées (comme nous l’avons dit, les données ne transitent que des parents vers...

La gestion des événements

Les événements sont la manière par laquelle il est possible de capturer les interactions de l’utilisateur avec l’interface. Il peut s’agit de clics de la souris, de saisie dans un champ de texte, de validation de formulaire, de défilement (scroll), etc. La manière de les gérer en React est similaire à celle du JavaScript natif, avec quelques différences syntaxiques.

En premier lieu, les noms d’événements sont en camelCase au lieu d’être en minuscules attachées. Par exemple, la syntaxe de l’événement de clic en React est onClick, alors que c’est onclick en HTML natif. Ensuite, la fonction de rappel chargée de gérer l’événement peut être passée directement à l’attribut, sans utiliser une syntaxe avec une chaîne de caractère. Par exemple, onclick="onclick()" devient onClick={() => { ... }}. Enfin, les fonctions représentant des événements se voient injecter un objet contenant les données relatives à l’interaction. Cet événement n’est pas identique en JavaScript natif et en React, qui passe par une abstraction, SyntheticEvent. L’abstraction SyntheticEvent est un wrapper autour des objets d’événements natifs garantissant un comportement identique sur tous les navigateurs.

Lorsque la fonction de rappel dans l’attribut fait une action unique, il est possible de l’écrire comme une fonction anonyme directement dans la prop. Néanmoins...

La propriété children et les injections de JSX

1. Le principe de la propriété children

Pour une architecture robuste, la grande majorité des balises HTML peuvent accepter du contenu imbriqué entre leurs balises. Les quelques balises qui ne le peuvent pas sont dites « orphelines ». Tel est le cas de <img> ou <input> par exemple. Jusqu’ici, tous les composants que nous avons construits sont également orphelins. Pour obtenir des composants flexibles et réutilisables, il peut être nécessaire d’y injecter du contenu JSX. Si les composants peuvent être écrits via une syntaxe <MyComponent />, ils peuvent aussi être écrits via une syntaxe <MyComponent></MyComponent/>, ce qui implique que des éléments JSX puisse être introduits entre la balise ouvrante et la balise fermante du composant.

En React, tout ce qui est inséré entre les balises ouvrante et fermante d’un composant est représenté par la prop children. Cette prop peut être de n’importe quel type : un morceau de code JSX, une chaîne de caractère, un nombre, une fonction, un tableau d’éléments JSX, etc. En somme, tout ce qui peut être rendu. Le rôle principal de children est d’incarner le principe de composition, qui est la méthode de prédilection pour la réutilisation du code en React. En effet, l’héritage de composants n’est concrètement pas possible. La composition, c’est-à-dire le fait d’imbriquer des composants les uns dans les autres - ou les uns à côté des autres - est donc le moyen de prédilection pour construire des applications en React.

Il existe de nombreuses manières d’indiquer qu’un composant accepte la prop children. Nous en retiendrons deux, qui sont les plus utilisées. Tout d’abord, il est possible de traiter children comme une prop classique de l’interface définissant les props du composant. Son type de prédilection est ReactNode, qui est un type flexible représentant toutes les valeurs que peut prendre la prop children.

Bien sûr, une fois que le fonctionnement des types est bien acquis, on peut réaliser que n’importe quelle prop peut...

Les listes de composants

La plupart des applications web ne se contentent pas d’afficher un seul élément à la fois ; elles présentent des collections de données, comme des listes de produits, des commentaires sur un blog, des listes d’utilisateurs, ou d’articles. Comment gérer l’affichage de ces listes dynamiques en React de manière efficace et performante ? C’est ce qui sera exploré ici.

1. Listes d’éléments HTML

Commençons par le cas le plus simple. Imaginons que l’on souhaite afficher une liste de fruits. L’affichage d’un tableau se fait par l’utilisation de la fonction JavaScript .map. Cette méthode crée un nouveau tableau en appliquant une fonction de rappel à chaque élément du tableau d’origine. Utilisons-la pour convertir nos données JavaScript en fragments JSX.

Puisqu’en JSX les fragments JSX sont traités comme étant des valeurs comme les autres, les fonctions de rappel de .map peuvent tout autant retourner ces fragments. Il est important de respecter une structure HTML cohérente : par exemple, on entourera la liste d’une balise <ul> et chaque élément sera entouré d’une balise <li>.

export default function App() { 
  const fruits = ["Apple", "Banana", "Pineapple"] 
 
  return ( 
    <ul> 
      {fruits.map((fruit) => <li>{fruit}</li>)} 
    </ul> 
  ); 
} 

Le code précédent a néanmoins un défaut et va provoquer l’avertissement suivant :

Warning: Each child in an array or iterator should have a unique "key" prop. 

Pour rendre des listes d’éléments de manière efficace, React se base sur l’identification de chaque élément du tableau avec une prop spéciale : key. Sans cette identification unique et stable, React serait incapable de savoir quels éléments ont été ajoutés, supprimés, modifiés ou réordonnés dans le tableau. Il aura tendance à déclencher beaucoup plus de rendus...

Le routeur

Une application web contient le plus souvent non pas une, mais plusieurs pages. Jusqu’ici, tous les composants créés peuvent être visualisés dans une page web via l’URL racine /. Pour que l’application reste aussi dynamique que possible, React ne permet de créer que des SPA (Single Page Application - application à page unique). Cela ne veut pas dire qu’il n’est pas possible d’avoir plusieurs pages, mais que la navigation d’une page à une autre ne fonctionne pas exactement comme le feraient les pages d’un site web reliées par une balise d’URL <a>, par exemple.

Ainsi, la navigation entre différentes pages via React se fait sans recharger intégralement la vue du navigateur. Cette navigation n’est pas incluse par défaut dans React, une bibliothèque externe est par conséquent nécessaire. Bien qu’il existe plusieurs bibliothèques de routeurs en React, la plus utilisée est sans nul doute React Router. Elle peut être installée en exécutant la commande npm install react-router-dom.

React Router met à disposition plusieurs composants qui permettent de gérer les différentes routes de l’application. Pour rendre le routeur utilisable, il faut d’abord indiquer à React que l’on souhaite utiliser un contexte de routeur. C’est à cela que sert le composant BrowserRouter. Il doit être ajouté au plus haut niveau de l’application pour que tous les composants aient accès au routeur. Il entoure ainsi le composant App dans le fichier main.tsx.

import { StrictMode } from "react"; ...

Les composants en classe

Ce chapitre ne sera pas nécessairement utile à un développeur voulant travailler sur des projets récents ou sur des projets personnels. Il s’adresse davantage aux développeurs ayant besoin de maintenir un code legacy (c’est-à-dire qui est tributaire des anciennes versions de React) et éventuellement de le faire évoluer vers un code utilisant des pratiques plus récentes.

Cela a été évoqué en introduction de ce chapitre, les composants en React ont pris historiquement la forme de classes et non pas de fonctions. Si les composants fonctionnels sont aujourd’hui la norme, de nombreux projets en entreprise disposent encore d’une base de code datant d’avant la version 16.8 de React (février 2019). C’est à partir de cette version que sont introduits les composants fonctionnels et que commencent à tomber en désuétude les composants de classe.

Jusqu’à cette version, les composants de classe étaient l’unique manière de créer des composants. Un composant de classe est une classe JavaScript ES6 qui hérite de la classe Component<T, U>. La classe Component<T, U> dispose d’une méthode abstraite render() qu’il est nécessaire de surcharger dans la déclaration de la classe. Cette fonction retourne...