:: Enseignements :: ESIPE :: E3INFO :: 2025-2026 :: Web et Géomatique ::
[LOGO]

React et Appels asynchrones


Le but de ce TP est de réaliser une application de sélection de vol d'avions (flights) et de trouver le vol ayant le prix le moins cher (Best Value).

La doc du Mozilla Developer Network MDN

Dans un premier temps, nous avons besoin de deux choses, installer les bibliothèques de React (react et react-dom) et récupérer l'outil esbuild (un exécutable), qui transforme les fichiers .jsx en fichier .js (et bundle les dépendances).
Pour récuperer esbuild, nous allons utiliser npm qui est le gestionnaire de libraries JavaScript et qui permet aussi de récupérer des exécutables (ce qui est stupide en termes de sécurité, mais c'est comme cela ...).
            npm install --save-exact --save-dev esbuild
        

La commande npm ci-dessus installe l'exécutable esbuild dans le répertoire ./node_modules en locale donc pour exécuter esbuild, on utilisera la commande
            ./node_modules/.bin/esbuild --version
        

Puis on va installer, toujours dans ./node_modules, les deux bibliothèques react et react-dom, toujours avec npm
            npm install --save-exact --save-dev react react-dom
        

On peut maintenant écrire un fichier JSX, flight.jsx puis le transpiler en JavaScript avec esbuild. On utilise pour cela la commande
            ./node_modules/.bin/esbuild flight.jsx --bundle --outfile=flight.js
        

Il est important de faire attention à la qualité du code que vous allez rendre. Avoir un code qui semble marcher, mais qui n'est pas maintenable, pas compréhensible ou qui contient du code mort (qui ne sert à rien) sera fortement pénalisé.

Voilà une idée graphique de l'application que l'on veut réaliser

Et voilà l'arbre DOM que l'on souhaite obtenir.

Exercice 1 - Flights

L'API REST du serveur est définie comme ceci:
  • Obtenir tous les vols: GET /api/flights
    Cet appel renvoi l'ensemble des vols au format JSON.
    Pour simuler les possibles changements de prix, à chaque requête, un des vols a son prix qui est changé de plus ou moins 10 dollars.
    Vous pouvez tester en copiant dans votre navigateur http://localhost:8080/api/flights.
  • Supprimer un vol: DELETE /api/flights/id
    Avec id, la valeur de l'id de l'évènement que l'on veut supprimer. Cet appel renvoi un code 200 si cela s'est bien passé.

Pour démarrer, on va utiliser le fichier flight.html suivant

<!DOCTYPE html>
<html>
  <head>
  <meta charset="utf-8">
  <link rel="icon" href="data:,">
  <script src="flight.js" type="text/javascript"></script>
  <style>
  .app {
    text-align: center;
    margin: 20px;
  }

  button {
    margin: 10px;
    padding: 8px 16px;
    cursor: pointer;
    border-radius: 20px;
    border: none;
    background-color: #007bff;
    color: white;
  }

  button:hover {
    background-color: #0056b3;
  }

  table {
    margin: 20px auto;
    border-collapse: collapse;
    width: 80%;
  }

  th, td {
    border: 1px solid #ddd;
    padding: 8px;
    text-align: left;
  }

  th {
    background-color: #dfdfdf;
    cursor: pointer;
  }

  /* Display the sort order */
  th.sort::after {
    content: " ↓";
  }

  tr:nth-child(even) {
    background-color: #f2f2f2;
  }

  /* Highlight the cheapest flight */
  tr.highlight {
    background-color: #ffff00af !important;
  }
  </style>
</head>
<body>
  <div id="App"></div>
</body>
</html>

            

Et pour le fichier flight.jsx suivant

import * as React from 'react';
import * as ReactDOM from 'react-dom/client';

function App() {
  return <div className="app"></div>;
}

window.onload = () => {
  const appDOM = document.getElementById("App");
  const root = ReactDOM.createRoot(appDOM);
  root.render(<App/>);
};

            

On utilisera de plus le serveur Java JExpress.java pour servir les fichiers flight.html et flight.js et l'API REST spécifique aux vols.

  1. Utiliser esbuild pour réécrire le fichier JSX en fichier JS puis lancer le serveur java JExpress.java dans le répertoire courant et vérifier avec un navigateur que l'application s'affiche bien à l'adresse http://localhost:8080/flight.html.
  2. Pour le moment, on va écrire tout le code dans le même fichier flight.jsx pour créer notre application.
    Il ne faudra pas oublier après chaque modification de relancer esbuild ou alors, vous pouvez utiliser l'option --watch.
    Créer un composants FlightList qui permet d'afficher les vols (flight) sous forme d'une table. Un vol est caractérisé par un aéroport de départ (from), un aéroport d'arrivée (to), un temp de vol (duration) et un prix (price).
    Pour récupérer les vols sur les vols, faite un appel asynchrone à l'API dans un useEffect.
    Pour l'affichage de la durée de vol, le serveur renvoie la durée en minutes, vous utiliserez la fonction suivante pour afficher la durée de vol en heure.
    function toHour(minutes) {
      return `${Math.floor(minutes / 60)}h ${minutes % 60}m`;
    }
                

    Pour les prix, ils sont en dollars.
    Pour trouver la structure exacte, utiliser l'image de l'arbre DOM et de l'application ci-dessus.
    Écrire le composant FlightList et visualiser que l'affichage est correcte.
    Note: pour l'instant, on ne s'occupe pas des boutons.
    Note2: penser que comme vous affichez une liste de vols, il ne faut pas oublier les clés pour React.

  3. Ajouter un composant DeleteButton à la fin de chaque ligne, qui permet de supprimer le vol correspondant.
    Pour éviter trop d'aller-retour au serveur, le bouton "Delete" va demander la suppression au serveur et si celle-ci est confirmée, supprimer la ligne dans l'affichage.
    Attention, on vous demande de ne pas refaire un accès au serveur pour demander à nouveau la liste des vols. Le changement au niveau de l'affichage est suffisant.

  4. Ajouter un composant RefreshButton qui permet de remettre à jour la liste des vols en redemandant au serveur la liste de vols. Le bouton doit être placé au-dessus de la table HTML.

  5. On souhaite maintenant ajouter un composant CheapestButton qui met en sur-brillance (highlight) le vol le moins cher parmi les vols affichés (il y a une classe pour cela dans le CSS).
    La surbrillance doit disparaitre lorsque l'on demande un ré-affichage des vols avec le bouton "Refresh Flights" car les prix peuvent avoir changé. Même chose si l'on demande la suppression d'un des vols.
    Pour trouver le vol le moins cher, vous pouvez faire une boucle sur les vols ou (bonus) utiliser la méthode reduce.
    Ajouter le composant à l'application.
    Note: vérifier que votre code ne plante pas si tous les vols ont été supprimée et que l'on demande le vol le moins cher !

  6. On souhaite maintenant découper le code en plusieurs fichiers.
    • Un fichier api.js qui contient les fonctions qui font des fetchs
    • Un fichier par gros composant
    • Un fichier pour l'application

    Utiliser export/import pour cela.
    Expliquer quel est le problème de l'import * en JS.
    Indiquer comment on supprime les import *.
    Supprimer les import *.

  7. On veut maintenant pouvoir trier l'affichage des vols en fonction de l'aéroport de départ (from). Pour cela, ajouter un composant qui permet de trier les vols si l'on clique sur le titre "From" de la table.
    Par défaut, aucun trie ne doit être fait, c'est uniquement lorsque l'utilisateur le demande que le trie doit être fait.
    Rappel: pour trier en JavaScript, on utilise une fonction de comparaison comme celle-ci
    function compareFlight(f1, f2) {
      if (f1.from < f2.from) {
        return -1;
      }
      if (f1.from > f2.from) {
        return 1;
      }
      return 0;
    }
                

  8. Vérifier que lors d'un trie si un vol est en surbrillance, il doit rester en surbrillance (il sera juste déplacé par le trie).
    Vérifier que si l'on rafraichit l'affichage en rechargeant les vols, le trie ne doit pas être remis à zéro.
    Faites les changements qui s'imposent.

  9. Enfin, modifier votre code pour qu'il marche aussi pour trier selon les autres colonnes (to, duration, price), sachant que l'on ne peut trier qu'une colonne à la fois.
    Attention, si vous avez trop de duplication dans votre code, je ne vais pas être content, essayer d'avoir un seul et même code qui fait les différents tris.

  10. Enfin, ajouter une flèche (regarder le CSS), qui indique visuellement la colonne qui est triée (s'il y en a une).