React
Quelques définitions
- Le page d'accueil du site react.dev ainsi que react.dev/learn proposent une bonne introduction aux composants react.
- Composition : combiner des composants avec d'autres composants.
- Un composant react est une fonction qui retourne du JSX (du HTML dans du JS).
Projet reactjs avec vite
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
# Lancer un serveur de développement
npm run dev
# Créer un build de production
npm run build
Dans le dossier src
, créer le dossier components
et y ajouter un fichier Hello.jsx
.
- Ajouter un composant
Hello
qui prend un propname
et afficheHello, {name}
. - Ajouter un composant
StateDemo
qui illustre l'état local avecuseState
.
Exercices
Basique
- Créer un composant
Counter
qui affiche un bouton+
et un bouton-
pour incrémenter et décrémenter un compteur. Initialiser le compteur à 42. - Créer un composant
ToLowerCase
qui prend un prop (ou un argument)text
et affiche le texte en minuscules. (💡 astuce:string.toLowerCase()
) - Créer un composant
EurToYen
qui permet de saisir des euros et affiche le montant en yens (1 euro = 130 yens). (💡 astuce: utiliser<input type="number" />
) - Créer un composant
ShowMax
qui prend deux nombres en props et affiche le plus grand. - Créer un composant
Guess
qui affiche un zone éditable numérique et un bouton. A chaque fois que l'utilisateur clique sur le bouton, le composant génère un nouveau nombre aléatoire entre 1 et 10 et affiche si le nombre saisi est trop grand, trop petit ou si c'est le bon nombre. (💡 astuce: utiliserMath.random()
pour générer un nombre aléatoire). - Créer un composant
CountConsonantsAndVowels
qui prend un proptext
et affiche le nombre de consonnes et de voyelles (aeiuyo) dans le texte. Instancier ce composant dans<App>
et faire en sorte que le prop soit alimenté via la valeur d'un texte editable isntancié dans<App>
. (💡 astuce: utiliserstring.match(/[aeiuyo]/gi)
pour compter les voyelles). - Créer un composant
Palindrome
qui prend un proptext
et affiche si le texte est un palindrome ou non. (💡 astuce: utiliserstring.split('').reverse().join('')
pour inverser une chaîne de caractères). - Créer un composant
Fibonacci
qui prend un propn
et affiche le n-ième terme de la suite de Fibonacci.
Solutions
ExoCounter.jsx
import { useState } from "react";
export default function ExoCount(){
const initialValue = 42;
// const [état, fonction de maj de l'état] = useState(val par défaut);
const [count, setCount] = useState(initialValue);
return <>
<button onClick={() => setCount(count + 1)}>+</button>
{count}
<button onClick={() => setCount(count - 1)}>-</button>
<button onClick={() => setCount(initialValue)}>Reset</button>
</>;
}
ExoCounter.jsx
import PropTypes from "prop-types";
export default function ExoLowerCase({ text }) {
const lowerCased = text.toLowerCase();
return (
<>
<ul>
<li>
Méthode 1 en calculant dans la partie code du composant: {lowerCased}
</li>
<li>Méthode 2 directement dans le html: {text.toLowerCase()}</li>
</ul>
</>
);
}
// la prp text est une chaîne de caractères obligatoire
ExoLowerCase.propTypes = {
text: PropTypes.string.isRequired,
};
EuroToYen.jsx
import { useState } from "react";
export default function EuroToYen() {
const [euro, setEuro] = useState(0);
const yen = euro * 165;
return (
<>
<label htmlFor="euro">Euros</label>
<input
type="number"
name="euro"
value={euro}
onChange={(event) => setEuro(event.target.value)}
/>
Yen: {yen}
</>
);
}
ShowMax.jsx
import PropTypes from "prop-types";
export default function ShowMax({ a, b }) {
const max = a >= b ? a : b;
let maxIf = a;
if (a > b) {
maxIf = a;
} else {
maxIf = b;
}
return (
<>
Max of {a} and {b} is {max}, {a >= b ? a : b} , {maxIf}
</>
);
}
ShowMax.propTypes = {
a: PropTypes.number.isRequired,
b: PropTypes.number.isRequired,
};
CountConsonantsAndVowels.jsx
import PropTypes from "prop-types";
export default function CountConsonantsAndVowels({ word }) {
// word.match(/[aeiuyo]/gi)? : renvoie un tableau qui peut être null et ? renvoie null au lieu de crasher
// ?? 0 Si le résultat est null, on renvoie 0
const vowelCount = word.match(/[aeiuyo]/gi)?.length ?? 0;
return (
<>
Vowels of {word}: {vowelCount}. Consonants: {word.length - vowelCount}
</>
);
}
CountConsonantsAndVowels.propTypes = {
word: PropTypes.string.isRequired,
};
Listes
- Créer un composant
ShowLengths
qui prend un propitems
(un tableau de chaînes de caractères) et affiche chaque élément suivi de sa longueur. (💡 astuce: utiliserstring.length
pour obtenir la longueur d'une chaîne de caractères).- Par exemple, si
items = ['un', 'deux', 'trois']
, le composant affiche:
- Par exemple, si
- Créer un composant
ShowAlternating
qui prend un propitems
(un tableau de chaînes de caractères) et affiche les éléments de la liste en alternant les couleurs de fond (par exemple, une ligne sur deux en gris). (💡 astuce: utiliserindex % 2 === 0
pour tester si l'index est pair).- Par exemple: si
items = ['un', 'deux', 'trois']
, le composant affiche:
- Par exemple: si
- Créer un composant
LoggerComponent
qui affiche un champ de texte éditable et un bouton Ajouter. Chaque fois que l'utilisateur clique sur le bouton Ajouter, le texte saisi est ajouté à une liste. Afficher la liste des textes saisis.- Par exemple, si l'utilisateur saisit "un", "deux" et "trois", le composant affiche:
- Créer un composant
LoggerComponentExtended
qui affiche un champ de texte éditable et un bouton Ajouter. Chaque fois que l'utilisateur clique sur le bouton Ajouter, le texte saisi est ajouté à une liste contenant également l'horodatage de l'ajout. Afficher la liste.- Par exemple, si l'utilisateur saisit "un", "deux" et "trois", le composant affiche:
- Créer un composant
EditableLogger
qui affiche un champ de texte éditable et un bouton Ajouter. Chaque fois que l'utilisateur clique sur le bouton Ajouter, le texte saisi est ajouté à une liste contenant également l'horodatage de l'ajout.- Afficher la liste en permettant d'éditer le corps (pas la date) de chaque ligne élément et de supprimer un élément.
- Par exemple, si l'utilisateur saisit "un", "deux" et "trois", le composant affiche:
- Ajouter les boutons sauvegarder et charger pour sauvegarder la liste dans le local storage et la charger au démarrage de l'application ou au clique sur le bouton charger.
Solutions
StringsLengths.jsx
import PropTypes from "prop-types";
/**
* To instanciate <StringLengths items={["un", "deux", "trois"]} />
* @param {{texts: string[]}}
* @returns
*/
export default function StringLengths({ texts }) {
const textsElements = texts.map((text, index) => (
<li key={index}>text ({text.length})</li>
));
return <ul>{textsElements}</ul>;
}
StringLengths.propTypes = {
texts: PropTypes.string.isRequired,
};
ShowAlternating.jsx
import PropTypes from "prop-types";
/**
* To instanciate <ShowAlternating items={["un", "deux", "trois"]} />
* @param {{texts: string[]}}
* @returns
*/
export default function ShowAlternating({ texts }) {
const textsElements = texts.map((text, index) => (
<li
key={index}
style={{ backgroundColor: index % 2 === 0 ? "grey" : "blue" }}
>
text ({text.length})
</li>
));
return <ul>{textsElements}</ul>;
}
ShowAlternating.propTypes = {
texts: PropTypes.string.isRequired,
};
Composition
- Créer un composant
SocialPost
qui prend en props les propriétésauthor
,date
,content
etavatar
. Afficher ces propriétés de façon jolie.- Par exemple, si
author = 'Alice'
,date = '2022-01-01'
,content = 'Hello world!'
etavatar = 'alice.jpg'
, le composant affiche (de façon pas jolie):
- Par exemple, si
- Créer un composant
SocialPostList
qui prend en propposts
(un tableau d'objets avec les propriétésauthor
,date
,content
etavatar
) et affiche une liste deSocialPost
. - Créer un composant
HomePage
qui affiche un logo, un titre et une liste deSocialPost
. Créer un composantAboutPage
qui affiche un logo, un titre et un texte de présentation. Dans le composantApp
, afficher les deux liens. Avec un booléenisHomePage
, afficher soit la page d'accueil, soit la page "à propos" selon le lien sur lequel on clique.
Router
- Créer un projet react avec vite et le template react.
npm create vite@latest my-react-app-2 -- --template react
. - Préparation
- Créer un composant
Home
qui affiche "Bienvenue sur la page d'accueil". - Créer un composant
About
qui affiche "À propos de nous". - Créer un composant
Contact
qui affiche "Contactez-nous".
- Créer un composant
- Nettoyer le composant
App
. - Installer
react-router-dom
avecnpm install react-router-dom
. - Dans
src/main.jsx
Créer une table de routage en ajoutant le contenu suivant:import { RouterProvider, createBrowserRouter } from "react-router-dom"; import Home from "./components/Home.jsx"; import Contact from "./components/Contact.jsx"; import About from "./components/About.jsx"; // Table de routage const router = createBrowserRouter([ { path: "/", element: <App />, children: [ { path: "/home", element: <Home />, }, { path: "/about", element: <About />, }, { path: "/contact", element: <Contact />, }, ], }, ]);
- modifier la partie
createRoot
pour utiliser<React.StrictMode>
et<RouterProvider>
(c'est lui va gérer les routes de l'application). - Il faut aussi importer
import ReactDOM from "react-dom/client";
. - Fichier complet:
src/main.jsx
import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App.jsx"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; import Home from "./components/Home.jsx"; import Contact from "./components/Contact.jsx"; import About from "./components/About.jsx"; const router = createBrowserRouter([ { path: "/", element: <App />, children: [ { path: "/home", element: <Home />, }, { path: "/about", element: <About />, }, { path: "/contact", element: <Contact />, }, ], }, ]); ReactDOM.createRoot(document.getElementById("root")).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> );
- modifier la partie
- Dans le composant
App
, ajouter un lien vers la page d'accueil, la page "à propos" et la page de contact ({" - "}
permet de forcer un espace avant et après le -). - Tester l'application en lançant
npm run dev
. Que constatez vous au niveau du rendu de votre app et de la barre d'adresse ? - Ajouter le outlet dans le composant
App
pour afficher les pages enfants. - Comme les composants sont des pages, il est recommandé de les déplacer dans le dossier
src/pages
. Appliquer cette convention à l'avenir. - On peut spécifier des paramètres dans des routes (par exemple pour afficher un item à partir d'une liste).
Astuces
- Pour activer la colorations des parenthèses, accolades et crochets dans VSCode, activer l'option "Bracket Pair colorization" dans les paramètres.
- L'extension indent-rainbow permet de colorer les indentations.