Il s'agit d'une version statique de l'intranet d'A. Jonquet, certaines fonctionnalités sont donc potentiellement non fonctionnelles.
Rejoindre la version dynamique 🔒
React
Navigation

Une application de partage de signets en React - partie 1

Ce TP est le premier d'une série où vous allez créer la base d'une application permettant d'afficher et de gérer une liste de signets.

Afin que les données puissent être partagées entre différents utilisateurs, elles seront centralisées dans une base de données et accédées à l'aide d'une API.

Pour simplifier la conception et la gestion de l'application, les données de l'application seront gérées à l'aide des contextes React et l'affichage des composants sera réalisé à l'aide d'un routeur.

Ce TP, se focalisera sur la mise en place du projet et la réalisation d'une première requête AJAX.

Remarque importante

Les notes des TP seront obtenues à partir de vos dépôts Git, vous devrez donc prendre grand soin de la qualité de ces dépôts et de leurs « commits ».

De manière similaire, les descriptions de vos « commits » devront être claires et informatives, afin de permettre l'évaluation de la progression de votre travail.

Objectifs de la séance

  • Utilisation d'une API de données
  • Utilisation des contextes React
  • Utilisation d'un routeur
  • Gestion de données asynchrones

Mise en place du projet

Vous allez créer un nouveau projet React qui se nommera r410-bookmarks. Vous ferez le nettoyage dans le répertoire pour ne laisser que les fichiers nécessaires et vous installerez les différents outils de qualité de code avec le support des prop-types.

Vous pouvez vous référer au premier TP pour cela.

Vous ajouterez la modification nécessaire à la structure de l'application et au CSS pour que la structure de base de votre application soit similaire à la maquette suivante :

Illustration de la structure de base de l'application

Vous fixerez la largeur de l'application, qui restera centrée dans la fenêtre du navigateur si sa largeur est supérieure. Et la hauteur de l'application devra utiliser tout l'espace disponible. La partie centrale devra occuper tout l'espace non requi par l'en-tête et le pied de page.

Puis, vous créerez un dépôt distant associé, nommé lui aussi « r410-bookmarks », et vous ferez un commit permettant de marquer le début du TP.

Travail à réaliser
  • Création du projet r410-bookmarks.
  • Structuration de la base de l'application.
  • Réalisation du commit initial du TP.

Une première requête

Vous allez commencer par afficher la liste des signets. Dans cette optique, vous allez créer un composant BookmarksList, qui réalisera une requête AJAX vers l'API et affichera, pour l'instant, la liste des noms de signets obtenus.

Dans un premier temps et afin d'organiser votre code, vous centraliserez tout le code relatif à l'API de donnée dans le fichier src/services/api/bookmarks.js. Vous y définirez la constante BASE_URL :

Vous y ajouterez une fonction fetchAllBookmarks() qui utilisera la constante BASE_URL pour réalisé une requête AJAX à l'aide la fonction fetch() vers la ressource « /bookmarks » de l'API. Elle retournera la promesse du contenu du JSON de la réponse de la requête AJAX.

Comme vous l'avez vu au semestre précédent, la fonction fetch() permet de réaliser une requête AJAX et de gérer le résultat asynchrone à l'aide de Promesses. Dans notre cas, la réponse sera de type JSON et le contenu sera obtenu à l'aide de la méthode json() de la réponse.

Vous pourrez ensuite créer le composant BookmarksList. Ce composant comportera une variable d'état bookmarksData contenant la liste des signets à afficher.

En utilisant un hook d'effet, vous réaliserez une requête vers l'API afin d'obtenir une liste des signets à afficher, que vous stockerez dans la variable d'état bookmarksData, lors de la réponse de l'API.

Dans un premier temps, vous vous contenterez d'afficher le nom de chaque signet, de manière similaire à la maquette suivante :

Illustration de la structure de la liste de signets

Le composant BookmarksList se composera d'un élément HTML de type section comportant une liste d'article affichant le nom de chaque signet. Vous utiliserez ensuite le composant BookmarksList dans le composant App.

Travail à réaliser
  • Création de la fonction fetchAllBookmarks() dans le fichier « src/services/api/bookmarks.js ».
  • Création du composant BookmarksList.
  • Utilisation du composant BookmarksList dans le composant App.

Le composant d'affichage d'une note

Vous allez avoir besoin d'afficher des notes, vous allez donc créer un composant Rating permettant d'afficher une note.

Le composant Rating recevra une props value contenant la note à afficher. Vous illustrerez la note à l'aide d'une icône étoile de Font Awesome. Et vous pourrez afficher la note en vous inspirant des maquettes suivantes :

Illustration de la structure de base de l'application Illustration de la structure de base de l'application

La props value peut contenir une valeur réelle avec de nombreuses décimales, vous prendrez soin de l'arrondir à la décimale la plus proche avant de l'afficher, à l'aide Math.round par exemple.

Travail à réaliser
  • Installation des icônes Font Awesome.
  • Arrondi de la note à la décimale la plus proche.
  • Création du composant Rating.

Affichage des signets

Vous créerez ensuite un composant BookmarkItem dont le rôle sera d'afficher un signet dans la liste des signets.

Ce composant recevra une propriété data contenant les données d'un des signets de la liste issue de l'API et affichera sa représentation de manière similaire à la maquette suivante :

Illustration de l'affichage d'un bookmark

Le composant affichera le nom du signet, qui sera le support d'un lien vers l'URL du signet. En plus du nom, la moyenne des notes et l'avatar de l'utilisateur ayant créé le signet seront affichés.

Pour afficher l'avatar d'un utilisateur, vous utiliserez un élément HTML img et pour obtenir l'URL de l'image, vous ajouterez une fonction avatarUrl(userId) au script « bookmarks.js ». Cette fonction recevra en paramètre l'identifiant d'un utilisateur et retournera l'URL de la ressource de l'API fournissant l'avatar de l'utilisateur correspondant.

Vous prendrez soin de définir les prop-types du composant.

Travail à réaliser
  • Création du composant BookmarkItem.
  • Ajout de la fonction avatarUrl(userId).
  • Utilisation du composant BookmarkItem dans le composant BookmarksList.

Extraction de la pagination

Si vous observez la réponse de la liste des signets, vous constaterez que le résultat est paginé et que votre application affiche systématiquement la première page de la requête. Vous allez ajouter le support de la pagination à votre application.

Les données de pagination exportées par l'API ne sont pas très faciles à manipuler. Avant de créer le composant de pagination, vous allez transformer les données de l'API en une structure plus exploitable par votre futur composant.

Dans cette optique, vous ajouterez un module JavaScript « paginationFromHydraView.js » dans le répertoire « src/services/transformers » de votre projet. Ce script exportera par défaut une fonction qui recevra en paramètre le contenu de la propriété hydra:view d'une réponse paginée de l'API et retournera un objet JavaScript comportant les propriétés suivantes :

  • current, une propriété obligatoire contenant la page courante (un nombre), extraite de la propriété @id de la vue Hydra.
  • first, une propriété optionnelle contenant la première page (un nombre), extraite de la propriété hydra:first de la vue Hydra.
  • previous, une propriété optionnelle contenant la page suivante (un nombre), extraite de la propriété hydra:previous de la vue Hydra.
  • next, une propriété optionnelle contenant la page précédente (un nombre), extraite de la propriété hydra:next de la vue Hydra.
  • last, une propriété optionnelle contenant la dernière page (un nombre), extraite de la propriété hydra:last de la vue Hydra.

La fonction retournera null si la pagination ne comporte qu'une page, par exemple si la propriété hydra:last n'est pas présente dans la réponse de l'API.

Pour simplifier l'extraction de la valeur de la page des différentes urls, vous pourrez utiliser la classe URLSearchParams.

Afin de tester la validité de votre fonction, vous afficherez le résultat de son utilisation sur la pagination de la liste de signets obtenue dans le composant BookmarksList.

Travail à réaliser
  • Création de la fonction paginationFromHydraView dans « paginationFromHydraView.js ».
  • Utilisation de cette fonction dans le composant BookmarksList.

Mise en place de la pagination

Vous ajouterez une variable d'état au composant BookmarksList stockant la pagination générée à partir de la propriété hydra:view de la réponse paginée de l'API.

Vous allez ensuite créer un composant Pagination recevant comme propriété la variable d'état précédente et affichant la page courante ainsi que des boutons vers les première et dernière pages et les pages précédente et suivante. Les boutons devront être désactivés lorsque les propriétés ne sont pas présentes dans la pagination.

Vous ajouterez une instance du composant Pagination au composant BookmarksList afin d'afficher l'interface de navigation de la pagination pour la liste des signets.

Travail à réaliser
  • Création du composant Pagination.

Changement de page de la liste des signets

Vous disposez maintenant d'une interface de navigation pour la liste des signets, mais celle-ci n'est pas encore fonctionnelle. Affin de pouvoir faire évoluer la page courante de la liste des signets, vous allez ajouter une variable d'état page au composant BookmarksList avec 1 comme valeur initiale.

Vous réaliserez la mise à jour de cette variable d'état lors du clic sur un des boutons du composant Pagination à l'aide d'une nouvelle props contenant une fonction de rappel, réalisant la mise à jour de la variable d'état page.

Vous pourrez ensuite ajouter un paramètre urlParams de type URLSearchParams à la fonction fetchAllBookmarks dans lequel seront spécifiés les paramètres de la requête AJAX, pour l'instant, il ne contiendra que la page souhaitée.

Pour finir, afin que la requête AJAX soit ré-exécutée lors de chaque modification de la variable d'état page, vous placerez cette variable d'état dans la liste des dépendances du hook d'effet encapsulant la requête.

Travail à réaliser
  • Ajout d'une variable d'état page stockant la page courante.
  • Ajout d'une props au composant Pagination permettant de mettre à jour la variable d'état page.
  • Transmission de la page à la requête AJAX.
  • Mise à jour de la liste des signets lors du changement de page.

Indicateur de chargement

Afin d'améliorer l'expérience utilisateur, il est courant d'utiliser un indicateur de chargement lors du chargement de ressources.

Vous commencerez par créer un nouveau composant Loading.

Dans le composant BookmarksList, vous initialiserez la variable d'état contenant la liste des signets à null avant chaque requête AJAX.

Lors de l'affichage, vous ferez en sorte d'afficher le composant Loading en lieu et place du tableau de composants BookmarkItem lorsque la liste des signets vaut null.

Travail à réaliser
  • Création du composant Loading.
  • Affichage conditionnel du composant Pagination dans BookmarksList.
A. Jonquet DUT-INFO/REIMS