a) React et les composants
Développement "old school" d'applications web
Introduction
Avant d'entrer dans le vif du sujet, nous allons découvrir une application associée à une pizzeria qui a été développée "old school" en pur HTML / JS / CSS.
Nous allons rapidement voir comment cette application a été développée, et pourquoi il est intéressant de développer autrement. Nous vous recommandons de ne pas passer plus de 10 minutes à la découverte de cette application "old school", car il n'est pas nécessaire de comprendre en détail le code de cette application pour la suite de ce cours.
Veuillez télécharger le code source de cette application ici : Pizzeria Old School.
Cette application est aussi disponible ici : old-school.
Décompressez le fichier et placez le contenu dans le dossier /tutorials/front/old-school
de votre repo git.
Exécution de l'application "old school"
Veuillez installer l'extension Live Server
au sein de VS Code.
Veuillez ensuite exécuter index.hmtl
en faisant un clic droit sur ce fichier dans l'explorer de VS Code, puis Open with Live Server
.
Structure de l'IHM
Veuillez observer la structure de l'IHM de cette application web en parcourant très rapidement le fichier index.html
. Celui-ci contient un header, un main et un footer.
Le header contient un titre animé, le main contient un message et un lecteur audio, et le footer contient un titre animé et une image.
Gestion des assets
Pour intégrer une image ou un son dans une page HTML, il suffit d'utiliser une balise <img>
ou <audio>
.
Le footer contient une image stockée dans /img/js-logo.png
:
html<img src="./img/js-logo.png" alt="" />
Le main contient un lecteur audio avec un son stocké dans /sound/Infecticide-11-Pizza-Spinoza.mp3
:
html<audio id="audioPlayer" controls autoplay><source src="./sound/Infecticide-11-Pizza-Spinoza.mp3" type="audio/mpeg" />Your browser does not support the audio element.</audio>
Ces ressources sont publiées à l'aide de chemins relatifs spécifiés dans les attributs src
.
Mise en forme
A l'aide de CSS, cette application est stylée dans : /stylesheets/style.css
. Jetez un rapide coup d'oeil à ce fichier.
Le layout de la page fait toujours, au minimum, la hauteur complète du navigateur grâce :
- à un body repris comme un élément Flexbox faisant 100% de hauteur.
- le
main
qui est stylé pour remplir l'espace disponible.
Ainsi, le footer donne l'effet d'être "sticky" en bas de page.
De plus, /img/pizza.jpg
est utilisé comme background de l'élément html
.
Cette balise dans index.html
, à la fin de la balise head
, permet d'appliquer la stylesheet à index.html
:
html<link rel="stylesheet" href="./stylesheets/style.css" />
Ajout d'interactivité
Un script nommé /index.js
permet de gérer les clics des utilisateurs sur la page et de stopper / redémarrer la musique. Veuillez parcourir très rapidement ce fichier.
L'interactivité est ajoutée à la page en utilisant un script JS qui est inclus à la fin de la balise body
de index.html
:
html<script src="./index.js"></script>
Ajout d'une librairie externe
La librairie Animate.css [R.32] a été ajoutée pour gérer une animation. Voici comment la librairie est appelée au sein de /index.html
:
html<linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
L'application offre un titre qui rebondit en utilisant la classe CSS animate__animated animate__bounce
de cette librairie directement au sein de /index.html
:
html<h1 class="animate__animated animate__bounce">We love Pizza</h1>
Pourquoi développer autrement ?
Bien que cette application fonctionne, elle n'est pas très maintenable. Le plus gros souci est la gestion des dépendances. En effet, si vous souhaitez mettre a jour la librairie Animate.css
, vous devrez le faire manuellement. Et que se passe-t-il si vous avez des dizaines de librairies à gérer ?
De plus, la gestion du rendu de la page est assez complexe et pas optimisé. C'est ainsi que React est né : pour simplifier la création d'IHM complexes et pour gérer les mises à jour de l'IHM de manière efficace.
Mise en place d'un projet Vite + React + TS
Choix des technologies
Comme annoncé dans l'introduction (voir Introduction), nous allons développer nos Interfaces-Homme-Machine (IHM) à l'aide de React.
React est une librairie JS développée par Facebook en 2013. Elle est utilisée pour créer des interfaces utilisateur (UI) interactives et réactives.
React est basé sur des composants, des éléments réutilisables qui permettent de structurer une application web.
Nous allons utiliser Vite pour la création de nos projets web. Vite est un outil de développement permettant de développer des applications web avec des technologies modernes comme React, Vue, Svelte, TypeScript, SCSS, CSS, etc.
Et plutôt que de faire du React en JavaScript, nous allons utiliser TypeScript, que vous connaissez déjà un peu grâce à la partie 1 de ce cours.
Finalement, nous allons utiliser SWC qui est un transpiler TypeScript/JavaScript écrit en Rust. Il permet de transpiler du code TypeScript en JavaScript très rapidement.
Création d'un projet Vite + React + TypeScript + SWC
Création du projet en mode interactif
Nous allons créer notre premier projet React nommé components
au sein de notre repo git.
Au sein de VS Code, ouvrez un terminal dans le dossier de votre repo git contenant les tutorials (par exemple clic droit sur web2/tutorials
, Open in Integrated Terminal
) et tapez la commande suivante :
bashnpm create vite@latest
Veuillez choisir comme nom de projet components
et ces technos:
- React
- TypeScript + SWC (Speedy Web Compiler, Rust-based)
Pour exécutez votre projet, veuillez taper les commandes suivantes :
bashnpm inpm run dev
Création du projet en une seule ligne de commande
Il est possible de créer un projet avec une seule ligne de commande, sans passer par le mode interactif, en sélectionnant les technologies appliquées dans ce cours :
bashnpm create vite@latest PROJECT_NAME -- --template react-swc-ts
Les composants React
Veuillez observer le code de votre projet. Vous avez un fichier App.tsx
qui définit un "React component" ayant le nom App
.
Ce composant est en fait une fonction JavaScript. Elle ressemble à cela :
tsxfunction App() {return (// Qqch qui ressemble à de l'HTML)}export default App
Un composant React doit :
- toujours commencer par une majuscule ! Sinon React ne serait pas capable de distinguer entre de simples balises HTML et vos composants.
- doit renvoyer un seul élément. Par exemple, cela n'est pas autorisé et ne compilerait pas (car renvoi de 3 éléments) :
tsxfunction App() {return (<Header title="We love Pizza" version={0+1} /><Main /><Footer />);}
Nous pourrions soit renvoyer tout cela dans une div
, ou utiliser un "fragment", un élément vide (<></>
) :
tsxfunction App() {return (<><Header title="We love Pizza" version={0+1} /><Main /><Footer /></>);}
Un composant React est donc généralement une fonction qui doit être exportée à la fin du fichier.
⚡️ N'oubliez jamais d'exporter vos composants React s'ils doivent être importé dans un autre script !
NB : Pour rappel, il y a plusieurs façons de définir des fonctions en JS : function arrows, fonctions nommées, fonctions anonymes... Nous verrons cela plus en détails plus tard.
main.tsx
s'occupe de rendre le composant App
dans une div
qui a un id dont la valeur vaut root
dans index.html
.
Voici le code de main.tsx
où l'on va récupérer l'accès à la div#root
(css selector pour indiquer la div
qui a l'id
root) via document.getElementById('root')
:
jsReactDOM.createRoot(document.getElementById('root')!).render(<React.StrictMode><App /></React.StrictMode>,)
💭 Qu'est-ce que l'opérateur !
ci-dessus ?
Il permet d'assurer au compilateur que document.getElementById('root')
ne sera jamais nul... Cela fait partie de la "null safety"... Nous allons expliciter tout cela plus tard.
Qu'est-ce que <React.StrictMode>
? Le StrictMode est conçu pour vous aider à écrire des applications robustes et évolutives tout en adoptant les meilleures pratiques recommandées par l'équipe de React : aide à la détection de problèmes comme des pratiques dépréciées, double rendu temporaire en développement pour détecter des effets secondaires lors d'opération de lecture & écriture d'états dans des composants...
⚡️ Pensée pour plus tard...
Pensez à vous souvenir, si un jour vous ne comprenez pas pourquoi un composant est rendu 2 fois au lieu d'une... c'est probablement que vous êtes en StrictMode
...
Voici le code de index.html
:
html<!doctype html><html lang="en"><head><meta charset="UTF-8" /><link rel="icon" type="image/svg+xml" href="/vite.svg" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Vite + React + TS</title></head><body><div id="root"></div><script type="module" src="/src/main.tsx"></script></body></html>
TSX
Introduction
Regardez bien le fichier App.tsx
: il semblerait que les composants React retournent des balises HTML.
Mais ça n'est pas le cas !
Bien que TSX ressemble à de l'HTML, c'est finalement du JS qui sera compilé...
Nous allons voir comment le code TSX est transpilé en JavaScript, et comment il est exécuté par le navigateur.
Transpilation/Compilation
- Transpilation TypeScript vers JavaScript: Le code TSX est transpilé en JavaScript par le compilateur TypeScript (tsc). Ce processus convertit le code TypeScript en code JavaScript tout en supprimant les annotations de type.
- Conversion JSX/TSX vers JavaScript: Le JSX/TSX est également transformé en appels
React.createElement
, qui est la forme JavaScript compréhensible par le moteur JavaScript. Par exemple, pour ce composant TSX permettant d'afficher un message de bienvenue (nous verrons plus tard la syntaxe associée) :
tsximport React from 'react';interface GreetingProps {name: string;}const Greeting = ({ name }: GreetingProps) => {return <h1>Hello, {name}!</h1>;};export default Greeting;
Ce composant ci-dessus serait compilé en JavaScript de la manière suivante :
tsxconst Greeting = ({ name }) => {return React.createElement("h1", null, `Hello, ${name}!`);};
Exécution
Le code résultant est du JavaScript standard. Les navigateurs exécutent ce code JavaScript. Ils ne comprennent pas TypeScript directement, donc tout le code TypeScript doit être transpilé en JavaScript avant l'exécution.
En conclusion, bien que les composants soient écrits en TypeScript (TSX) pour bénéficier de ses fonctionnalités, le code exécuté par React et le navigateur est du JavaScript.
Pour rentrer dans le vif du sujet, nous allons convertir l'application associée à une pizzeria qui a été développée "old school", et l'intégrer dans notre environnement Vite React TS SWC...
Veuillez copier le code HTML dans App.tsx
afin de créer les éléments TSX correspondants :
tsximport "./App.css";function App() {return (<><header><h1 class="animate__animated animate__bounce">We love Pizza</h1></header><main><p>My HomePage</p><p>Because we love JS, you can also click on the header to stop / start themusic ; )</p><audio id="audioPlayer" controls autoplay><sourcesrc="./sound/Infecticide-11-Pizza-Spinoza.mp3"type="audio/mpeg"/>Your browser does not support the audio element.</audio></main><footer><h1 class="animate__animated animate__bounce animate__delay-2s">But we also love JS</h1><img src="./img/js-logo.png" alt="" /></footer></>);}export default App;
Pour adapter le code "old school" à React, il faut transformer :
class
enclassName
autoplay
enautoPlay
Veuillez ajouter le fichier audio du projet old-school
dans : /src/assets/sounds/Infecticide-11-Pizza-Spinoza.mp3
.
Veuillez changer le chemin vers le fichier audio dans App.tsx
:
tsx<audio id="audioPlayer" controls autoplay><sourcesrc="./assets/sounds/Infecticide-11-Pizza-Spinoza.mp3"type="audio/mpeg"/>Your browser does not support the audio element.</audio>
Ca ne fonctionne pas ! En effet, vous utilisez Vite comme module bundler. Le fichier n'est pas servi là où vous le pensez.
Gestion des assets avec Vite : sons & images
Introduction
Lors de la compilation, vos assets (fichiers statiques tels que des images, des sons, des vidéos, des scripts...) pourrons être optimisés par votre module bundler et se trouveront dans un répertoire et sous un nom que vous ne maîtrisez pas.
Pour connaître le chemin exact de votre fichier après le build, vous devez le demander à votre application en faisant un import
.
Import de sons
Veuillez changer App.tsx
pour y importer le fichier son de la pizzeria :
tsximport sound from "./assets/sounds/Infecticide-11-Pizza-Spinoza.mp3"// Reste du code<audio id="audioPlayer" controls autoPlay><sourcesrc={sound}type="audio/mpeg"/>Your browser does not support the audio element.</audio>
La variable sound
contient le chemin du fichier son lors de la compilation.
Import d'images
A partir du projet old-school
, veuillez ajouter les deux images js-logo.png
et pizza.jpg
et le svg pizza-svgrepo-com.svg
dans /src/assets/images
.
Dans App.tsx
, veuillez commencer par importer les deux images :
tsximport logo from "./assets/images/js-logo.png";import pizzaBackground from "./assets/images/pizza.jpg";
Ces deux variables peuvent être utilisées comme chemins dans nos balises img
.
Pour le footer, il est simple de faire le lien vers le logo de JS :
tsx<footer><h1 className="animate__animated animate__bounce animate__delay-2s">But we also love JS</h1><img src={logo} alt="" /></footer>
Par contre, pour avoir une image de background, ça n'est pas si évident. Pour rappel, React s'occupe d'offrir un point d'accès au fichier index.html
, à une div#id
qui se trouve dans le body
.
Une des façons de faire, c'est que nous pourrions créer une nouvelle balise div
comme premier élément de App
, et changer son style
pour avoir une backgroundImage
:
tsxfunction App() {return (<div style={{ backgroundImage: `url(${pizzaBackground})` }}><header><h1 className="animate__animated animate__bounce">We love Pizza</h1></header><main><p>My HomePage</p><p>Because we love JS, you can also click on the header to stop / startthe music ; )</p><audio id="audioPlayer" controls autoPlay><source src={sound} type="audio/mpeg" />Your browser does not support the audio element.</audio></main><footer><h1 className="animate__animated animate__bounce animate__delay-2s">But we also love JS</h1><img src={logo} alt="" /></footer></div>);}
Veuillez regarder le résultat visuel actuel dans votre browser. Cela n'est pas très beau, il y a du travail à faire au niveau du CSS.
Gestion du CSS
Introduction
Nous souhaitons reprendre le style de l'application initial, tout en intégrant la philosophie proposée par React pour gérer les fichiers .css
.
Style général du layout de toutes les pages
Pour ce faire, nous voyons que index.css
permet de gérer le style de index.html
, pour ce qui concerne principalement le style de la balise html
et body
.
Nous allons remplacer index.css
par ce contenu afin d'ajouter une image d'une pizza en background :
csshtml,body {height: 100%;margin: 0;padding: 0;}html {background-image: url(./assets/images/pizza.jpg);background-size: cover;}
On peut voir ici avec url(./assets/images/pizza.jpg)
que notre outil Vite
va s'occuper d'importer le fichier pizza.jpg
et de récupérer le bon chemin vers ce fichier lors du build.
Style des composants React
Chaque composant React devrait pouvoir être réutilisé facilement dans d'autres applications. Ainsi, il est intéressant d'attacher les feuilles de style à leur composant React.
Si l'on considère le composant App
, son style va être géré par un fichier nommé App.css
qui se trouvera dans le même dossier que App.tsx
.
Veuillez donc donner le style à votre composant App
en remplaçant le contenu de App.css
par celui-ci :
cssdiv#root {height: 100%;display: inline-block; /* avoid margins to collapse to avoid vertical scrollbar */width: 100%;}.page {height: 100%;display: flex;flex-direction: column;text-align: center;}header {text-align: center;}main {text-align: center;/*to easily deal with sticky footer:grow the main to fill the space*/flex: 1 0 auto;}footer {text-align: center;}footer img {height: 50px;}footer h1 {color: white;}
Nous avons créé un classe page
qui doit être appliquée à notre première balise div
dans App.tsx
:
tsxfunction App() {return (<div className="page">
Veuillez visualiser l'état de notre application : elle commence à ressembler à quelque chose !
Création de composants React
Introduction
Il est intéressant de pouvoir structurer ses applications en plusieurs composants potentiellement réutilisables dans d'autres applications.
Si l'on regarde attentivement notre composant App
, nous voyons qu'il y a 3 grandes parties :
- Un
Header
qui devrait être le même sur toutes les éventuelles futures pages. - Un
Main
qui reprendra le contenu intéressant associé à chaque page. - Un
Footer
qui là aussi devrait être le même sur toutes les éventuelles futures pages.
Dès lors, nous pourrions créer trois composants React pour mieux structurer notre page.
Création de composants internes à un composant
Si nous partions de ces hypothèses :
- nous ne souhaitons jamais réutiliser le
Header
, leMain
et leFooter
à l'extérieur deApp.tsx
, - le code de
App.tsx
n'est pas trop volumineux, alors il est totalement acceptable de considérer créer ces composants à l'intérieur du moduleApp
.
NB : Nous appelons un module tout script que nous pouvons importer dans notre application.
Voici comment nous pouvons créer 3 composants React et les utiliser au sein du composant App
. Veuillez mettre à jour App.tsx
:
tsxfunction App() {return (<div className="page"><Header></Header><Main /><Footer /></div>);}const Header = () => {return (<header><h1 className="animate__animated animate__bounce">We love Pizza</h1></header>);};const Main = () => {return (<main><p>My HomePage</p><p>Because we love JS, you can also click on the header to stop / start themusic ; )</p><audio id="audioPlayer" controls autoPlay><source src={sound} type="audio/mpeg" />Your browser does not support the audio element.</audio></main>);};const Footer = () => {return (<footer><h1 className="animate__animated animate__bounce animate__delay-2s">But we also love JS</h1><img src={logo} alt="" /></footer>);};export default App;
Nous voyons que chaque nouveau composant a été défini ici comme une function arrow.
Ensuite, afin d'utiliser un composant, nous créons ce que nous appelons un élément React d'un composant. Ici, <Header />
est un élément du composant Header
.
Tout comme en HTML, la balise <Header />
est la contraction de <Header></Header>
.
Notre code devient nettement plus lisible avec ces nouveaux composants.
Il se lit comme une histoire, j'ai une App
qui est constituée de 3 éléments... Si je veux les détails de chaque composant associé à un élément, il suffit d'aller plus bas et de lire le code associé.
Éléments multiples
Si nous souhaitons avoir trois Headers
dans notre page, il suffit de faire appel trois fois à <Header/>
au sein de App
:
tsxfunction App() {return (<div className="page"><Header/><Header/><Header/><Main /><Footer /></div>);}
Les props et la définition de type
Les props
Il est intéressant de pouvoir passer des données à ses composants. Nous le faisons à l'aide de ce que nous appelons en React, des props.
Cela va nous permettre de créer des composants "configurables" via leur props. C'est intéressant car ça va nous amener à bénéficier de composants plus facilement réutilisables dans différents contextes.
Par exemple, ici, Header
devrait pouvoir offrir une propriété permettant de définir le titre du header. Transformons Header
ainsi :
tsxconst Header = (props) => {return (<header><h1 className="animate__animated animate__bounce">{props.title}</h1></header>);};
Si vous faites cela et que vous avez installé et activé votre Linter (plus de détails plus loin, l'extension ESLint de VS Code doit être installée), vous verrez que cette fonction JavaScript amène à cette erreur dans votre éditeur de code : Parameter 'props' implicitly has an 'any' type
.
Notez aussi que malgré les erreurs de lecture statique de votre code, votre code compile...
Néanmoins, il est important d'écrire du code propre.
En TypeScript, nous devons spécifier les types des variables au minimum pour les cas où TypeScript ne peut pas "inférer" (ou déduire) le type.
Définition de types
Pour rappel, pour définir un type en TS, il y a deux principales façons de le faire. Soit à l'aide de type
, soit à l'aide de interface
.
Dans ce cours, nous avons choisi d'utiliser interface
pour définir la structure d'objets.
Voici comment on défini de la manière la plus claire et la plus concise un type pour les props du composant Header
:
tsxinterface HeaderProps {title: string;}const Header = (props: HeaderProps) => {return (<header><h1 className="animate__animated animate__bounce">{props.title}</h1></header>);};
Le type HeaderProps
est composé d'un title
uniquement. Le paramètre du composant Header
reçoit un objet de ce type (via le props:HeaderProps
) contenant toutes les props que l'utilisateur du composant définit.
Pour le composant Header
, TS est capable d'inférer le type de retour de la fonction React. Si l'on avait voulu, on aurait pu expliciter le type de retour en JSX.Element
ainsi :
tsxconst Header = (props: HeaderProps): JSX.Element => {return (<header><h1 className="animate__animated animate__bounce">{props.title}</h1></header>);};
Nous estimons que dans ce cas, il n'est pas utile d'expliciter le type de retour.
Il aurait aussi été possible d'utiliser du inline prop type annotation pour typer props
ainsi :
tsxconst Header = (props: {title:string}) => {return (<header><h1 className="animate__animated animate__bounce">{props.title}</h1></header>);};
Cette notation, sans utiliser les interface, est acceptable dans les cas où vous avez des composants très simples, avec peu de props, ou en phase de prototypage (pour aller vite).
👍 Néanmoins, en règle générale, vous devez utiliser interface
pour définir le type de composants que vous souhaitez réutiliser, afin d'améliorer la lisibilité (cohérence entre tous les composants) et la maintenabilité de votre code.
Voici comment on passe les props à un élément React :
tsxfunction App() {return (<div className="page"><Header title="We love Pizza"/><Main /><Footer /></div>);}
Si l'on souhaitait ajouter une deuxième propriété qui indiquerait un numéro de version, on pourrait le faire ainsi.
tsxinterface HeaderProps {title: string;version:number;}const Header = (props: HeaderProps) => {return (<header><h1 className="animate__animated animate__bounce">{props.title}</h1><h4>Version: {props.version}</h4></header>);};
💭 On voit que le linter indique une erreur si on ajoute pas la props version
lorsqu'on créé un élément. Pourtant l'application compile toujours...
Si l'on souhaite se forcer à écrire du code propre, ça n'est pas une bonne chose que ça compile. Nous verrons plus loin comment afficher les erreurs de linter dans le browser.
Nous allons maintenant ajouter le numéro de version attendu par notre élément de type Header
:
tsxfunction App() {return (<div className="page"><Header title="We love Pizza" version={0+1} /><Main /><Footer /></div>);}
Nous voyons que lorsque nous passons des props, nous pouvons donner comme valeur d'une props le résultat d'une expression JavaScript. Toute expression JavaScript (ici une bête addition : {0+1}
) doit être placée entre accolade au sein du code TSX.
Si nécessaire, vous pouvez trouver le code associé à ce tutoriel ici : components.
Exercice 2.1 : Création de composants intégrés
Veuillez créer un nouveau projet en utilisant les technos Vite + React + TS + SWC nommé /exercises/2.1-2-3-4
dans votre git repo.
Veuillez supprimer les fichiers non utilisés (.css
, assets...).
Voici le code de départ du composant App
(à mettre dans App.tsx
) :
tsxconst App = () => {const pageTitle = "Informations sur les films dans les cinémas";const cinema1Name = "UGC DeBrouckère";const cinema1Movie1Title = "Film 1 - DeBrouckère";const cinema1Movie1Director = "Director A";const cinema1Movie2Title = "Film 2 - DeBrouckère";const cinema1Movie2Director = "Director B";const cinema2Name = "UGC Toison d'Or";const cinema2Movie1Title = "Film 1 - Toison d'Or";const cinema2Movie1Director = "Director C";const cinema2Movie2Title = "Film 2 - Toison d'Or";const cinema2Movie2Director = "Director D";return (<div><h1>{pageTitle}</h1><div><h2>{cinema1Name}</h2><ul><li><strong>{cinema1Movie1Title}</strong> - Réalisateur :{" "}{cinema1Movie1Director}</li><li><strong>{cinema1Movie2Title}</strong> - Réalisateur :{" "}{cinema1Movie2Director}</li></ul></div><div><h2>{cinema2Name}</h2><ul><li><strong>{cinema2Movie1Title}</strong> - Réalisateur :{" "}{cinema2Movie1Director}</li><li><strong>{cinema2Movie2Title}</strong> - Réalisateur :{" "}{cinema2Movie2Director}</li></ul></div></div>);};export default App;
Le code n'est pas très propre 😱.
Veuillez faire un "refactor" de ce code afin que deux nouveaux composants permettent :
- d'afficher le titre de la page
- d'afficher toutes les informations associées au premier cinema
- d'afficher toutes les informations associées du deuxième cinéma
Les nouveaux composants doivent se trouver dans App.tsx
.
S'il y a de l'info à donner à un composant, faites le à l'aide des props. Même si ça n'est pas des plus propres, un composant Cinema
reçoit toutes les infos sans créer de nouveaux types abstrait (comme Movie
par exemple).
⚡️ Veuillez avancer pas à pas et ne pas tenter de programmer tous vos composants d'un coup. Une fois qu'un composant fonctionne, passez alors seulement au suivant ; )
Voila à quoi ressemblera App
:
tsxconst App = () => {const pageTitle = "Informations sur les films dans les cinémas";// ... for const definitionsreturn (<div><PageTitle title={pageTitle} /><Cinemaname={cinema1Name}movie1Title={cinema1Movie1Title}// .../><Cinemaname={cinema2Name}//.../></div>);};
Une fois tout fonctionnel, veuillez faire un commit avec le message suivant : new:ex2.1
Exercice 2.2 : Meilleure gestion des types
Nous allons continuer le projet de votre exercice précédent qui se trouve dans le dossier /exercises/2.1-2-3-4
dans votre repo git.
Nous avons vu précédemment qu'il est recommandé, pour un code propre, de définir des types pour chacune des props de nos composants.
De plus, notre client nous a donné une nouvelle version des données d'entrée du composant App
qui n'est pas parfaite, mais qui s'améliore. Voici ces données, ainsi qu'une idée du résultat du composant App
:
jsconst App = () => {const pageTitle = "Informations sur les films dans les cinémas";const cinema1Name = "UGC DeBrouckère";const movie1 = {title: "HAIKYU-THE DUMPSTER BATTLE",director: "Susumu Mitsunaka",};const movie2 = {title: "GOODBYE JULIA ",director: "Mohamed Kordofani",};const cinema2Name = "UGC Toison d'Or";const movie3 = {title: "THE WATCHERS",director: "Ishana Night Shyamalan",};const movie4 = {title: "BAD BOYS: RIDE OR DIE",director: "Adil El Arbi, Bilall Fallah",};return (<div><PageTitle title={pageTitle} /><Cinema name={cinema1Name} movie1={movie1} movie2={movie2} /><Cinema name={cinema2Name} movie1={movie3} movie2={movie4} /></div>);};
Pour cet exercice nous souhaitons :
- qu'un type abstrait
Movie
soit créé qui contiendra untitle
et undirector
; - qu'un type abstrait
PageTitleProps
soit créé ; - qu'un type abstrait
CinemaProps
soit créé.
Veuillez mettre à jour votre composant Cinema
pour que tout soit fonctionnel.
Une fois tout fonctionnel, veuillez faire un commit avec le message suivant : new:ex2.2
💭 A la fin de cet exercice, nous nous rendons compte que le passage des informations à nos composants peut encore être amélioré... par exemple, un Cinema
devrait pouvoir recevoir des movies
au sein d'un tableau. De plus, il serait utile d'apprendre à externaliser nos composants dans des modules. Nous allons apprendre cela dans la suite du cours.
Le linter
Cet outil permet de détecter des erreurs de programmation lors de l'écriture de nos scripts. Par défaut, l'application Vite a créé une configuration du linter qui se trouve dans .eslintrc.cjs
.
Pour bénéficier de feedback sur votre code au sein de VS Code, veuillez installer l'extension ESLint. Vous avez même des propositions de "Quick fix" !
Pour ajouter les problèmes de linter dans le browser ainsi que dans le terminal, après la transpilation/compilation, vous devez utiliser un plugin.
- Installation du plugin
vite-plugin-checker
:
bashnpm i vite-plugin-checker -D
- Nouvelle configuration de Vite pour afficher les erreurs dans le browser dans
vite.config.ts
:
tsimport { defineConfig } from 'vite'import react from '@vitejs/plugin-react-swc'import checker from 'vite-plugin-checker'// https://vitejs.dev/config/export default defineConfig({plugins: [react(),checker({// e.g. use TypeScript checktypescript: true,}),],})
Le formatter
Pour formater facilement votre code, vous pouvez utiliser un "formatter". Nous recommandons l'utilisation de l'outil Prettier pour formater votre code.
Veuillez donc installer l'extension prettier au sein de VS Code.
Une fois prettier installé dans VS Code, vous pouvez facilement formatter votre code ainsi :
- soit en tapant
Shift Alt F
(Option Shift F
sous MacOS); - soit en faisant un clic droit sur votre script,
Format Document
; la première fois, il se peut que vous deviez sélectionner prettier comme formatter.