Guide de Cours Et TPs - M204 - React JS - Nov 2024
Guide de Cours Et TPs - M204 - React JS - Nov 2024
L’essentiel de React JS
1 / 158
What is React JS:
React is a front-end JavaScript library for building user interfaces (UI).
It was developed by facebook and maintained by facebook and the open
source community.
If you have npx and Node.js installed, you can create a React application by
using create-react-app.
What is create-react-app?
Create-react-app is a simple tool or a command that generates the required
files and folders to start the react application and run it in the browser. It is also
officially supported by the react team.
To use React in production, you need npm which is included with Node.js.
To run the create-react-app command you need to have node.js installed on
your PC.
npx create-react-app
Node is a javascript runtime that allows you to execute js code on the server
it is highly probable that you already have it installed but if you do not, go to
nodejs.org and download and install it.
After that, we can create an empty folder on our desktop let us call it
my_first_react_app and drag and drop it in Visual Studio Code.
C:\ . . . \my_first_react_app> npm install -g [email protected]
2 / 158
Run this command to run the React application my_first_react_app:
npm start
A new browser window will pop up with your newly created React App! If
not, open your browser and type localhost:3000 in the address bar.
1. Classes
ES6 introduced classes.
A class is a type of function, but instead of using the keyword function to
initiate it, we use the keyword class, and the properties are assigned inside
a constructor() method.
class Personne{
constructor(nom,age){
3 / 158
this.nom=nom;
this.age=age;
}
info(){
return 'Personne nom: ' + this.nom + ' a pour age: ' +
this.age;
}
}
document.write(p1.info());
document.write('<br>');
document.write(p2.info());
2. Héritage de classe
class Stagiaire extends Personne {
constructor(nom,age,filiere){
super(nom,age);
this.filiere=filiere;
}
info(){
return super.info() + ' de la filiere: ' +
this.filiere;
}
}
document.write(s1.info());
document.write('<br>');
document.write(s2.info());
4 / 158
3. Arrow Functions
Arrow functions allow us to write shorter function syntax:
Before we use normal syntax:
function Somme(a,b) {
return a + b;
}
document.write(Somme(2,4));
Or:
const Somme = function (a,b) {
return a + b;
}
document.write(Somme(10,20));
document.write(Somme(30,50));
document.write(Double(10));
4. Array Methods
map method :
One of the most useful in React is the .map() array method.
The .map() method allows you to run a function on each item in the
array, returning a new array as the result.
const personnes = [
{ nom: "Rami", age: 33, estMember: true },
5 / 158
{ nom: "Fatihi", age: 24, estMember: false },
{ nom: "Chakib", age: 45, estMember: true },
{ nom: "Mounir", age: 37, estMember: false },
];
Exercice 1:
Soit l’Array nums = [2, 5, 8, 7, 3].
Utiliser la méthode map pour créer un Array contenant les éléments de
nums
multipliés par 3.
nouvNums = [6, 15, 24, 21, 9].
filter method :
const personnes = [
{ nom: "Rami", age: 33, estMember: true },
{ nom: "Fatihi", age: 24, estMember: false },
{ nom: "Chakib", age: 45, estMember: true },
{ nom: "Mounir", age: 37, estMember: false },
];
// const persAgés=personnes.filter(function(pers){return
pers.age>=35})
const persAgés=personnes.filter(function(pers){return
pers.age>=35})
const personAgés = persAgés.map((pers) => pers.nom + ' ' +
pers.age + ' estMembre: ' + pers.estMember +' ');
document.write(personAgés);
Exercice 2 :
En utilisant les méthodes map et filter.
Créer un Array nompers à partir de l’Array personnes contenant les noms
des
personnes qui sont membre c-à-d estMember est true.
6 / 158
map((pers) => pers.nom);
document.write(personAgés);
find method :
Find method returns the first element of an array that satisfied a condition.
const personnes = [
{ nom: "Rami", age: 33, estMember: true },
{ nom: "Fatihi", age: 24, estMember: false },
{ nom: "Chakib", age: 45, estMember: true },
{ nom: "Mounir", age: 37, estMember: false },
];
// const pers1 = personnes.find(function(pers){return
pers.age>=45})
const pers1 = personnes.find((pers) => pers.age >= 45);
document.write(pers1.nom);
document.write(pers1);
reduce method :
const clients = [
{ nom: "Rami", montant: 4500 },
{ nom: "Karimi", montant: 2300 },
{ nom: "Chaouki", montant: 5500 },
{ nom: "Ramoun", montant: 7700 },
];
const
totalMontants=clients.reduce(function(total,client){
return total+=client.montant
7 / 158
},0);
document.write(totalMontants);
Destructuring Arrays
Exemple :
const voitures = ['Ford', 'BMW', 'Audi'];
Here is the old way of assigning array items to a variable:
// old way
const v1 = voitures[0];
const v2 = voitures[1];
const v3 = voitures[2];
document.write(v1,' ',v3);
document.write(v1,' ',v3);
8 / 158
Exemple :
function calculate(a, b) {
const add = a + b;
const subtract = a - b;
const multiply = a * b;
const divide = a / b;
Destructuring Objects
Old way
// Before:
const vehicleOne = {
brand: 'Ford',
model: 'Mustang',
type: 'car',
year: 2021,
color: 'red'
}
myVehicle(vehicleOne);
document.write(myVehicle(vehicleOne));
// old way
function myVehicle(vehicle) {
const message = 'My ' + vehicle.type + ' is a ' +
vehicle.color + ' ' + vehicle.brand + ' ' + vehicle.model +
'.';
return message;
}
9 / 158
With destructuring:
const vehicleOne = {
brand: 'Ford',
model: 'Mustang',
type: 'car',
year: 2021,
color: 'red'
}
myVehicle(vehicleOne);
document.write(myVehicle(vehicleOne));
myVehicle(vehicleOne);
10 / 158
document.write(myVehicle(vehicleOne));
Spread Operator
const T1 = [1, 2, 3];
const T2 = [4, 5, 6];
const T = [...T1, ...T2];
document.write(T)
document.write(rest)
const updateMyVehicle = {
type: 'car',
year: 2021,
color: 'yellow'
}
11 / 158
const myUpdatedVehicle = {...myVehicle, ...updateMyVehicle};
document.write(myUpdatedVehicle.brand);
document.write('<br>');
document.write(myUpdatedVehicle.model);
document.write('<br>');
document.write(myUpdatedVehicle.color);
document.write('<br>');
document.write(myUpdatedVehicle.type);
document.write('<br>');
document.write(myUpdatedVehicle.year);
Modules
JavaScript modules allow you to break up your code into separate files.
This makes it easier to maintain the code-base.
Export
You can export a function or variable from any file.
personne.js
const name = "Rachid";
const age = 25;
function Som(a,b) {
return a + b;
}
class Personne{
constructor(name, age) {
this.name = name;
this.age = age;
}
info(){
return '${this.name} a ${this.age} ans';
}
}
12 / 158
index.js
import { name,age, Som, Personne } from "./personne.js";
Default Exports
Let us create another file, named index.js, and use it for demonstrating default
export.
You can only have one default export in a file.
index.js
export const name = "Rachid";
export const age = 25;
info(){
return '${this.name} a ${this.age} ans';
}
}
Import
You can import modules into a file in two ways, based on if they are
named exports or default exports.
Named exports must be destructured using curly braces. Default
exports do not.
import { name,age, Som}, Personne from "./personne.js";
13 / 158
Exercice 3 :
Soit l’Array
const inscriptions = [
{id:10,nom:'Rami',filiere:'DEV'},
{id:11,nom:'Kamali',filiere:'DEV'},
{id:12,nom:'Fahmi',filiere:'DEV'},
{id:13,nom:'Chaouki',filiere:'DEV'}
];
Notion de Composant
1. Component.
return (
<div className="App">
<h1>Hello, {nom}!</h1>
</div>
);
}
14 / 158
const isNameShown = true;
return (
<div className="App">
<h1>Hello, {isNameShown? nom : 'someone'}!</h1>
</div>
);
}
return (
<div className="App">
<h1>{2 + 4}</h1>
</div>
);
}
function A() {
return (<h1>Hello A</h1>);
function B() {
return (<h1>Hello B</h1>);
}
function App() {
return (
15 / 158
<div className="App">
<A />
<A />
<A />
<B />
<B />
<B />
<B />
</div>
);
}
function A(props) {
return (
<h1>Hello, {props.nom} tu habites {props.ville}</h1>
);
}
function B(props) {
return (<h1>Article : {props.desi} coûte {props.pu} dhs</h1>);
}
function App() {
return (
<div className="App">
16 / 158
<A nom='Walid' ville='Fes'/>
<A nom='Rachid' ville='Casa'/>
<A nom='Alae' ville='Fes'/>
<B desi='Disque' pu={500}/>
<B desi='Souris' pu={100}/>
<B desi='Clé usb' pu={150}/>
<B desi='Imprimante' pu={2000}/>
</div>
);
}
Exemple 3 :
Composants dans des fichiers séparés (Export et import) :
A.jsx (ou A.js) :
function A(props){
return (
<div>
<h1>Hello, {props.client.nom} tu habites
{props.client.ville}</h1>
</div>
)
}
export default A;
17 / 158
}
export default B;
App.js :
import A from './A.jsx';
import B from './B.jsx';
function App() {
const client1 = {nom:'Walid', ville:'Fes'};
const client2 = {nom:'Rachid', ville:'Casa'};
const art1 = {desi:'Disque', pu:500};
const art2 = {desi:'Souris', pu:100};
return (
<div className="App">
<A client={client1}/>
<A client={client2}/>
<B article={art1}/>
<B article={art2}/>
</div>
);
}
export default A;
18 / 158
B.js
function B(props){
export default B;
Séance 4 : JSX
Créer une liste de cinq éléments en JSX
function App() {
return (
<div>
{liste}
</div>
);
}
Index.css
.red {
color : red;
}
19 / 158
function App() {
return (
<div>
{liste}
</div>
);
}
function App() {
return (
<div>
{liste}
</div>
);
}
function App() {
return (
<div>
{liste}
</div>
);
}
21 / 158
Séance 6 : Passage d’un Array dans props
App.js
import './App.css';
import Presentation from './Presentation';
function App() {
const personne1 = {nom:'Alami', prenom:'Rachid'}
const diplomes1 = ['Bac', 'Licence', 'Master']
const personne2 = {nom:'Tazi', prenom:'Wail'}
22 / 158
<hr className='hr'/>
<Presentation personne={personne2} diplomes={diplomes2}
/>
</div>
);
}
index.css
h2 {
font-size: 30px;
margin: 0;
}
h3 {
font-size: 24px;
margin: 0;
}
ul {
font-size: 20px;
margin: 0;
}
.hr {
height: 2px;
background-color: blue;
}
23 / 158
Séance 6 : Passage d’un Array dans props
App.js
import './App.css';
import Presentation from './Presentation';
function App() {
const personnes = [
{id:1,
nom:'Alami',
prenom:'Rachid',
diplomes:['Bac', 'Licence', 'Master']
},
{id:2,
nom:'Tazi',
prenom:'Wail',
diplomes:['Bac', 'Licence']
},
{id:3,
nom:'Sqalli',
24 / 158
prenom:'Meryem',
diplomes:['Bac', 'Ingénieur']
},
{id:4,
nom:'Karam',
prenom:'Moaad',
diplomes:['Bac', 'Technicien']
}
]
return (
<div className="App">
{personnes.map((personne) => (
<>
<Presentation key={personne.id} personne={personne} />
<hr className='hr'/>
</>
))}
</div>
);
}
index.css
h2 {
font-size: 30px;
margin: 0;
}
h3 {
font-size: 24px;
margin: 0;
}
ul {
font-size: 20px;
margin: 0;
}
25 / 158
.hr {
height: 2px;
background-color: blue;
}
return (
<button onClick={shoot}>Take the shot!</button>
);
}
App.js
import './App.css';
import Football from './Football.jsx';
26 / 158
function App() {
return (
<div className="App">
<Football />
</div>
);
}
Passing Arguments
Football.jsx
function Football() {
const shoot = (a) => {
alert(a);
}
return (
<button onClick={() => shoot("Goal!")}>Take the
shot!</button>
);
}
27 / 158
Arrow Function: Sending the event object manually:
function Football() {
const shoot = (a, b) => {
alert(b.type);
/*
'b' represents the React event that triggered the
function,
in this case the 'click' event
*/
}
return (
<button onClick={(event) => shoot("Goal!", event)}>Take
the shot!</button>
);
}
TP Séance 4 : Cards
28 / 158
alt="Photo"></img>
<h2>{props.nom}</h2>
<p>{props.description}</p>
</div>
)
App.js
import './App.css';
import Card from './Card.jsx';
import homme from './photos/homme.png';
import homme2 from './photos/homme2.PNG';
import femme from './photos/femme.png';
import femme2 from './photos/femme3.PNG';
function App() {
return (
<div className="App">
<Card image={homme} nom="Alami Rachid"
description="Stagiaire Dev Full Stack" />
<Card image={femme} nom="Naji Karima"
description="Stagiaire Dev mobile"/>
<Card image={homme2} nom="Tazi Morad"
description="Stagiaire Dev mobile" />
<Card image={femme2} nom="Wahbi Sanae"
description="Stagiaire Dev Full Stack" />
</div>
);
}
index.css
.card {
border: 1px solid #332f2f00;
border-radius: 10px;
box-shadow: 5px 5px 5px green;
29 / 158
padding: 20px;
margin : 10px;
text-align: center;
max-width: 250px;
display: inline-block;
;
}
.card .card-image {
max-width: 60%;
height: auto;
border-radius: 50%;
margin-bottom: 10px;
}
.card .card-title {
font-family: Arial, Helvetica, sans-serif;
margin: 0;
color: lightskyblue;
}
.card .card-text {
font-family: Arial, Helvetica, sans-serif;
color: green;
}
30 / 158
Exemple 2 : Personne component (Séance 4-2-travaux-pratique )
return (
<div className="produit">
<img className='produit-image' src={props.photo}
alt="Photo PC"></img>
<p>{props.desi}</p>
<p>{props.prix}</p>
<button>Ajouter au Panier</button>
</div>
31 / 158
)
}
App.js
import './App.css';
import Produit from './Produit.jsx';
function App() {
const produits = [
{
id: 1,
desi: 'PC Portable Gamer HP VICTUS',
prix: '7490 DH',
photo : './images/PC1.jpg'
},
{
id: 2,
desi: 'PC Portable Gamer HP VICTUS',
prix: '2190 DH',
photo : './images/PC2.jpg'
},
{
id: 3,
desi: 'Pc Portable Chromebook Acer',
prix: '3640 DH',
photo: './images/PC3.jpg'
},
{
id: 4,
desi: 'PC Portable - HUAWEI',
prix: '1270 DH',
photo: './images/PC4.jpg'
}
];
return (
32 / 158
<div className="App">
{produits.map((produit) => (
<Produit key={produit.id} desi={produit.desi}
prix={produit.prix} photo={produit.photo} />
))}
</div>
);
}
index.css
.produit {
border: 1px solid black;
border-radius: 10px;
box-shadow: 5px 5px 5px #0dbc0d;
padding: 6px;
margin: 6px;
text-align: center;
max-width: 250px;
display: inline-block;
}
.produit .produit-image {
max-width: 60%;
height: auto;
border-radius: 10%;
margin-bottom: 0;
}
p {
font-family: Arial, sans-serif;
font-size: 20px;
font-weight: bold;
margin: 6px;
color: blue;
}
button {
font-size: 20px;
33 / 158
font-weight: bold;
color: black;
background-color: orange;
}
import './App.css';
import { useState } from "react";
import ReactDOM from "react-dom/client";
function Voiture() {
const [marque, setMarque] = useState("Ford");
const [modele, setModele] = useState("Fiesta");
const [annee, setAnnee] = useState("2020");
const [couleur, setCouleur] = useState("rouge");
return (
<>
<h1>Ma voiture {marque}</h1>
<p>
34 / 158
est une {modele} {couleur} from {annee}.
</p>
</>
)
}
function App() {
return (
<div className="App">
<Voiture />
</div>
);
}
Or, we can just use one state and include an object instead!
import './App.css';
import { useState } from "react";
import ReactDOM from "react-dom/client";
function Voiture() {
const [voiture, setVoiture] = useState({
marque: "Ford",
modele : "Fiesta",
annee: "2020",
couleur:"rouge"
});
return (
<>
<h1>Ma voiture {voiture.marque}</h1>
<p>
est une {voiture.modele} {voiture.couleur}
from {voiture.annee}.
</p>
</>
)
}
35 / 158
function App() {
return (
<div className="App">
<Voiture />
</div>
);
}
import './App.css';
import { useState } from "react";
import ReactDOM from "react-dom/client";
function Voiture() {
const [voiture, setVoiture] = useState({
marque: "Ford",
modele : "Fiesta",
annee: "2020",
couleur:"rouge"
});
return (
<>
<h1>Ma voiture {voiture.marque}</h1>
<p>
est une {voiture.modele} {voiture.couleur}
from {voiture.annee}.
</p>
<button
type="button"
onClick={updateColor}
>Bleu</button>
36 / 158
</>
)
}
function App() {
return (
<div className="App">
<Voiture />
</div>
);
}
Example 1 :
import { useState, useEffect} from "react";
function App() {
const [text, setText] = useState('posts')
useEffect(() => {
console.log('render')
}, [text])
return (
<>
<div>
<button onClick={() => setText('posts')}>Posts</button>
<button onClick={() => setText('users')}>Users</button>
<button onClick={() =>
setText('comments')}>Comments</button>
</div>
37 / 158
<h1>{text}</h1>
</>
);
}
Example 2 :
import { useState, useEffect} from "react";
function App() {
const [windowWidth, setwindowWidth] =
useState(window.innerWidth)
return (
<div>
{windowWidth}
</div>
);
}
function App() {
const [windowWidth, setwindowWidth] =
useState(window.innerWidth)
38 / 158
setwindowWidth(window.innerWidth)
}
useEffect(() => {
window.addEventListener('resize', Redim)
}, [])
return (
<div>
{windowWidth}
</div>
);
}
Forms component :
import './App.css';
function Form1() {
return (
<form>
<label>Enter your name:
<input type="text" />
</label>
</form>
)
}
function Form2() {
return (
<form>
<label>Enter your name:
<input type="text" />
</label>
<button>Ok</button>
</form>
39 / 158
)
}
function App() {
return (
<div className="App">
<Form1 />
<Form1 />
<Form1 />
<Form2 />
<Form2 />
</div>
);
}
Exemple :
const Person = () => { This is a component
return (
<>
<h1>Name: Walid</h1>
<h2>Last Name: Alami</h2>
<h2>Age: 30</h2>
</>
)
}
41 / 158
<h2>Age: 30</h2>
</>
)
}
3. Props.
const Person = (props) => {
return (
<>
<h1>Name: {props.name}</h1>
<h2>Last Name: {props.lastname}</h2>
<h2>Age: {props.age}</h2>
</>
)
42 / 158
}
1. State.
State in React is a plain javascript object used by React to represent a piece
of information about the component’s current situation.
It is completely managed by the component itself.
So how can we actually create a state in React:
First, we have to import useState hook
import { useState } from 'react';
import './App.css';
43 / 158
+ 1
)}>+</button>
</div>
);
}
The very important thing is that all of this is happening without a website
reload.
useEffect(() => {
alert('Reload')
})
return (
<div className="App">
<button onClick={() => setCounter((prevCount) =>
prevCount - 1)}>-</button>
<h1>{counter}</h1>
<button onClick={() => setCounter((prevCount) =>
prevCount + 1)}>+</button>
44 / 158
</div>
);
}
Now, how to change our state to be 100 as soon as the page loads.
If we want to do something like this, counter = 100 that’s going to cause an
error.
import { useState, useEffect } from 'react';
import './App.css';
useEffect(() => {
counter = 100; Error
})
return (
<div className="App">
<button onClick={() => setCounter((prevCount) => prevCount –
1 )}>-</button>
<h1>{counter}</h1>
<button onClick={() => setCounter((prevCount) => prevCount +
1 )}>+</button>
</div>
);
}
45 / 158
export default App;
That’s because we are breaking a most important rule of React : never
modify state manually. Counter is not a normal variable it is a part of the
React state and React state can only be chaged by using its own setter
function.
So, we simply call a set counter:
useEffect(() => {
setCounter(100);
})
return (
<div className="App">
<button onClick={() => setCounter((prevCount) => prevCount –
1 )}>-</button>
<h1>{counter}</h1>
<button onClick={() => setCounter((prevCount) => prevCount +
1 )}>+</button>
</div>
);
}
46 / 158
const App = () => {
const [counter, setCounter] = useState(0);
useEffect(() => {
setCounter(100);
}, [])
return (
<div className="App">
<button onClick={() => setCounter((prevCount) =>
prevCount - 1)}>-</button>
<h1>{counter}</h1>
<button onClick={() => setCounter((prevCount) =>
prevCount + 1)}>+</button>
</div>
);
}
import './App.css';
function Form1() {
return (
<form>
<label>Enter your name:
<input type="text" />
</label>
</form>
)
47 / 158
}
Handling Forms
Use the useState Hook to manage the input:
function Form1() {
const [inputs, setInputs] = useState({});
return (
<form onSubmit={handleSubmit}>
<label>Enter your name:
<input
type="text"
name="username"
value={inputs.username || ""}
onChange={handleChange}
/>
</label>
<label>Enter your age:
<input
type="number"
name="age"
value={inputs.age || ""}
onChange={handleChange}
/>
</label>
<input type="submit" />
</form>
)
}
49 / 158
Affichage du nom (majuscule) et prenom (majuscule) saisis
dans le formulaire.
Inscription.jsx
function Inscription(props){
return (
<>
<h2>Inscription</h2>
<div>
<label>Nom:</label> <input
type="text"/>
</div>
<br/>
<div>
<label>Prenom:</label><input type="text"/>
</div>
<br/>
<button>Afficher</button>
<p>Information</p>
</>
)
}
App.js
import './App.css';
import Inscription from './Inscription.jsx';
50 / 158
function App() {
return (
<div>
<Form1 />
</div>
);
}
Inscription.jsx
function Inscription(){
const [nom,setNom]=useState()
const [prenom,setPrenom]=useState()
const [information,setInformation]=useState()
function afficher(){
setInformation(`nom:${nom} prenom:${prenom}`)
}
return(
<>
<h2>Inscription</h2>
51 / 158
<div>
<label>Nom:</label> <input
type="text"
onChange={(e)=>{setNom(e.target.value.toUpperCase())}}/>
</div>
<br/>
<div>
<label>Prenom:</label>;  <input type="text"
onChange={(e)=>{setPrenom(e.target.value.toUpperCase())}}/>
</div>
<br/>
<button onClick={afficher}>Afficher</button>
<p>{information}</p>
</>
)
}
function App() {
return (
<div>
<Inscription />
</div>
);
}
52 / 158
Ajout des informations saisies dans un tableau d’objets
personne ({id : . . . , nom : . . . , prenom : . . . })
Inscription.jsx
import React, { useState } from "react";
let nextId = 0;
function Inscription(){
function ajouter(){
const personne = {id:++nextId, nom:nom, prenom:prenom}
setT([...T, personne])
}
return(
<>
<h2>Inscription</h2>
<div>
<label>Nom:</label> <input type="text"
onChange={e => setNom(e.target.value)}/>
</div>
<br/>
<div>
<label>Prenom:</label><input type="text"
53 / 158
onChange={e => setPrenom(e.target.value)}/>
</div>
<br/>
<button onClick={ajouter}>Ajouter</button>
<p>{T.length}</p>
{T.map((person) => (
<div key={person.id}>{person.id} - {person.nom} -
{person.prenom}</div>
))}
</>
)
}
Travail à faire :
1- Affichage dans un tableau: <table></table>
2 - Affichage à l'aide d'un composant.
54 / 158
Inscription.jsx
import React, { useState } from "react";
let nextId = 0;
function Inscription(){
function ajouter(){
const personne = {id:++nextId, nom:nom, prenom:prenom}
setT([...T, personne])
}
return(
<>
<h2>Inscription</h2>
<div>
<label>Nom:</label> <input
type="text"
onChange={e => setNom(e.target.value)}/>
</div>
<br/>
<div>
<label>Prenom:</label><input type="text"
onChange={e => setPrenom(e.target.value)}/>
55 / 158
</div>
<br/>
<button onClick={ajouter}>Ajouter</button>
<p>{T.length}</p>
<table>
<tr
className="th"><td>Id</td><td>Nom</td><td>Prenom</td></tr>
{T.map((person) => (
<tr key={person.id}
className="tr"><td>{person.id}</td><td>{person.nom}</td><td>{p
erson.prenom}</td></tr>
))}
</table>
</>
)
}
index.css
table {
text-align: center;
border-collapse: collapse;
}
td {
border : 2px solid green;
width: 80px;
}
.th {
background-color: lightblue;
font-weight: bold;
}
.tr {
background-color: yellow;
}
56 / 158
Inscription.jsx
import React, { useState } from "react";
import Personne from "./Personne";
let nextId = 0;
function Inscription(){
function ajouter(){
const personne = {id:++nextId, nom:nom, prenom:prenom}
setT([...T, personne])
}
function supprimer(idP) {
setT(p => {
return T.filter(p => p.id !== idP)
})
}
return(
<>
<h2>Inscription</h2>
57 / 158
<div>
<label>Nom:</label> <input
type="text"
onChange={e => setNom(e.target.value)}/>
</div>
<br/>
<div>
<label>Prenom:</label><input type="text"
onChange={e => setPrenom(e.target.value)}/>
</div>
<br/>
<button onClick={ajouter}>Ajouter</button>
<p>{T.length}</p>
<table>
<tr
className="th"><td>Id</td><td>Nom</td><td>Prenom</td><td>Suppri
mer </td></tr>
{T.map((person) => (
<tr key={person.id} className="tr">
<td>{person.id}</td>
<td>{person.nom}</td>
<td>{person.prenom}</td>
<td><button onClick={() =>
supprimer(person.id)}>Supprimer</button></td></tr>))}
</table>
</>
)
}
let k = 0;
function Inscription(){
const [nom, setNom] = useState()
58 / 158
const [prenom, setPrenom] = useState()
const [T, setT] = useState([])
function ajouter () {
const personne = {id:++k, nom:nom, prenom:prenom}
setT([...T, personne])
}
const supprimer = idP => setT(p => T.filter( p => p.id != idP))
return(
<>
<h2>Inscription</h2>
<div>
<label>Nom
:</label> <input type="text"
onChange={e => setNom(e.target.value.toUpperCase())}/>
</div>
<br/>
<div>
<label>Prenom :</label> <input type="text"
onChange={e => setPrenom(e.target.value.toUpperCase())}/>
</div>
<br/>
<button onClick={ajouter}>Afficher</button>
<p>{T.length}</p>
<table>
<tr
className="th"><td>Id</td><td>Nom</td><td>Prenom</td><td>Suppri
mer</td></tr>
{T.map(person =>
<tr className="tr"
key={person.id}><td>{person.id}</td><td>{person.nom}</td><td>{p
erson.prenom}</td><td><button onClick={() =>
supprimer(person.id)}>Supprimer</button></td></tr>
)}
</table>
</>
)
}
59 / 158
export default Inscription;
Personne.jsx
import './index.css'
return (
<div className='personne'>
<h1>{id}</h1>
<h2>{nom}</h2>
<h3>{prenom}</h3>
</div>
)
}
Inscription.jsx
import React, { useState } from "react";
import Personne from "./Personne";
let nextId = 0;
function Inscription(){
function ajouter(){
const personne = {id:++nextId, nom:nom, prenom:prenom}
setT([...T, personne])
}
return(
<>
<h2>Inscription</h2>
<div>
<label>Nom:</label> <input
type="text"
onChange={e => setNom(e.target.value)}/>
</div>
<br/>
<div>
<label>Prenom:</label><input type="text"
onChange={e => setPrenom(e.target.value)}/>
</div>
<br/>
<button onClick={ajouter}>Ajouter</button>
<p>{T.length}</p>
{T.map((person) => (
<Personne key={person.id} personne={person} />
))}
</>
)
}
.personne {
border: 1px solid green;
61 / 158
border-radius: 10px;
box-shadow: 5px 5px 5px yellow;
padding: 4%;
margin: 2%;
text-align: center;
max-width: 100px;
display: inline-block;
}
Personne.jsx
function Personne (props) {
const {id, nom, prenom} = props.personne
function supprimerP(event) {
props.supprimerIns(id)
}
return (
<div className="personne">
<h1>{id}</h1>
<h2>{nom}</h2>
<h3>{prenom}</h3>
<button onClick={event =>
supprimerP(event)}>Supprimer</button>
</div>
)
}
62 / 158
export default Personne;
Inscription.jsx
import { useState } from "react";
import Personne from './Personne'
let k = 0;
function Inscription(){
const [nom, setNom] = useState()
const [prenom, setPrenom] = useState()
const [T, setT] = useState([])
function ajouter () {
const personne = {id:++k, nom:nom, prenom:prenom}
setT([...T, personne])
}
return(
<>
<h2>Inscription</h2>
<div>
<label>Nom
:</label> <input type="text"
onChange={e => setNom(e.target.value.toUpperCase())}/>
</div>
<br/>
<div>
<label>Prenom :</label> <input type="text"
onChange={e => setPrenom(e.target.value.toUpperCase())}/>
</div>
<br/>
<button onClick={ajouter}>Afficher</button>
<p>{T.length}</p>
{T.map(person =>
<Personne key={person.id} personne = {person}
supprimerIns = {supprimer}/>
)}
63 / 158
</>
)
}
64 / 158
componentDidMount(){
//cette methode est executé aprés render
console.log("Component Did mount")
console.log('--------------------')
}
componentDidUpdate(){
//cette methode est executé aprés mise à jour par
setState
console.log("Component Did update")
console.log('--------------------')
}
componentWillUnmount(){
console.log("Component est demonté")
}
render(){
console.log('Render')
return(
<div style={{background:"yellow"}} >
<h3>composant Compteur</h3>
<p>compteur:{this.state.compteur}</p>
<button onClick={this.incrementer}>Incrementer</button>
<button onClick={this.decrementer}>Decrementer</button>
</div>
)
}
}
componentDidMount
componentDidUpdate
componentWillUnmount
useEffect accepte deux paramètres. Le premier est un rappel qui s'exécute
après le rendu, un peu comme dans componentDidMount.
65 / 158
Le deuxième paramètre est le tableau des dépendances d'effet. Si vous
souhaitez l'exécuter uniquement lors du montage et du démontage, passez
un tableau vide [].
Séance 8 :
Communication inter-composant
(Envoi, réception de données)
Nous avons trois composants : App, ChercherBar et ResultatList :
66 / 158
ChercherBar.jsx
import React, { useState } from 'react';
function ChercherBar(props) {
const [typeX, setTypeX] = useState('')
function chercherbar(event) {
event.preventDefault()
props.chercherTyp(typeX)
}
return (
<div className='component'>
<h1>Chercher Bar</h1>
<label>Entrer le mot clé de recherche :</label>
<br/>
<input type="text" onChange={e =>
setTypeX(e.target.value.toLowerCase())}/><br/>
<button onClick={event =>
chercherbar(event)}>Chercher</button>
</div>
)
}
67 / 158
export default ChercherBar;
App.js
import React, { useState } from 'react'
import ChercherBar from './components/ChercherBar'
import ResultatList from './components/ResultatList'
const list=[
{nom:"banane",type:"fruit"},
{nom:"orange",type:"fruit"},
{nom:"pomme",type:"fruit"},
{nom:"raisins",type:"fruit"},
{nom:"kiwi",type:"fruit"},
{nom:"tomate",type:"legume"},
{nom:"carotte",type:"legume"},
{nom:"pomme de terre",type:"legume"},
{nom:"navet",type:"legume"},
{nom:"poivron",type:"legume"}
]
function App() {
const [type, setType] = useState('')
const [resultats, setResultats] = useState([])
function chercher(type){
setType(type)
setResultats(list.filter((item) =>
(item.type.toLowerCase()==type)))
}
return (
<div className='App'>
<h1>Composant App</h1>
<ChercherBar chercherTyp = {chercher}/>
<div>
<p>le type:<span style={{color:"rgb(36,44,33)",
fontWeight:"bold"}}>{type}</span></p>
</div>
<ResultatList list = {resultats}/>
</div>
68 / 158
);
}
ResultatList.jsx
function ResultatList(props) {
return (
<div className='component'>
<h1>Resultat List</h1>
<ul>
{props.list.map((item) => (
<li key={item.nom}>{item.nom}</li>
))}
</ul>
</div>
)
}
index.css
.App {
background-color: lightgreen;
max-width: 260px;
padding: 10px;
margin: 5px;
}
.component {
background-color: goldenrod;
max-width: 220px;
align-content: center;
padding: 10px;
margin: 10px;
}
h1 {
padding: 0px;
margin: 0px;
}
69 / 158
The event. preventDefault() line prevents the form from actually
submitting, giving you a chance to validate or process the input before
submitting it to the server or updating the state of your React component.
function App() {
return (
<div className="App">
<Bouton />
</div>
);
}
index.css
.boutonStyle {
70 / 158
color: blue;
border-color: green;
padding: 10px;
background-color: yellow ;
}
Bouton.js
function Bouton() {
return (
<button className='boutonStyle'>Nom du bouton</button>
);
}
function App() {
return (
71 / 158
<div>
<Bouton>Nom du bouton</Bouton>
</div>
);
}
Un autre exemple :
App.js
import styled from 'styled-components';
function App() {
return (
<Wrapper>
<Title>
Hello World!
</Title>
</Wrapper>
);
72 / 158
}
Connecte.js
function Connecte() {
return (
<h1>Bienvenue !</h1>
);
}
Anonymous.js
function Anonymous() {
return (
<h1>Veuillez vous inscrire.</h1>
);
}
Identification.js
import Anonymous from './Anonymous';
import Connecte from './Connecte';
73 / 158
function Identification(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <Connecte />;
}
return <Anonymous />;
}
App.js
import Identification from "./components/Identification";
function App() {
return (
<Identification isLoggedIn={false} />
);
}
NameForm.js
import { useState } from "react";
return (
<form onSubmit={handleSubmit}>
<label>
Nom :
<input type="text" name="nom" value={nom}
onChange={handleChange} />
</label>
<input type="submit" value="Envoyer" />
<br/>
<p>{info}</p>
</form>
);
};
function App() {
return (
<div className="App">
<NameForm />
</div>
);
}
75 / 158
TextArea.jsx
import { useState } from "react";
const handlerFocus=()=>{
setMessage("");
}
return (
<div>
<textarea cols={props.cols}
rows={props.rows}
value={message}
onFocus={handlerFocus.bind(this)}
onChange={handlerChange.bind(this)} />
<p>{message}</p>
</div>
);
};
76 / 158
App.js
import TextArea from "./components/TextArea";
function App() {
return (
<div className="App">
<TextArea cols={40} rows={10} value="Tapez votre texte ici"
/>
</div>
);
}
Select.jsx
import { useState } from "react";
const handlerChange=(event)=>{
setInfo('key='+event.target.value);
}
return (
<div>
<select onChange={handlerChange.bind(this)}>
77 / 158
{props.options.map(function(option, index) {
return <option key={index+1}
value={index+1}>{option}</option>
})
}
</select>
<p>{info}</p>
</div>
);
};
function App() {
return (
<div className="App">
<Select options={T} />
</div>
);
}
Select.jsx
import { useState } from "react";
78 / 158
const handlerChange=(event)=>{
setvaleur(event.target.value);
}
return (
<div>
<select onChange={handlerChange.bind(this)}
value={valeur}>
{props.options.map(function(option, index) {
return <option key={index+1}
value={option}>{option}</option>
})
}
</select>
<p>{valeur}</p>
</div>
);
};
function App() {
return (
<div className="App">
<Select options={T} />
</div>
);
}
79 / 158
RadioGroup.jsx
import { useState } from "react";
var radios = [
80 / 158
{ value : 1, text : "radio1"},
{ value : 2, text : "radio2" },
{ value : 3, text : "radio3", checked : true },
{ value : 4, text : "radio4" }
];
function App() {
return (
<RadioGroup radios={radios} name="group1"/>
);
}
RadioGroup.jsx
import { useState, useEffect } from "react";
81 / 158
return (
<div> {
props.radios.map((radio, index) => {
return (
<label key={index+1}>
<input type="radio"
value={radio.text}
name={props.name}
defaultChecked = {radio.checked}
onChange={onOptionChange}/>
<span>{radio.text}</span><br/>
</label>
)
}) }
<p>Selected option is : {valeur}</p>
</div>
);
};
RadioBouton.jsx
function RadioBouton (props) {
function optionChange(event) {
props.onOptionChange(event.target.value);
}
return (
<label>
<input type="radio"
value={props.text}
82 / 158
name={props.name}
defaultChecked = {props.checked}
onChange={event => optionChange(event)}/>
<span>{props.text}</span><br/>
</label>
)
}
RadioGroup.jsx
import { useState, useEffect } from "react";
import RadioBouton from "./RadioBouton";
83 / 158
</div>
);
};
var radios = [
{ value : 1, text : "radio1"},
{ value : 2, text : "radio2" },
{ value : 3, text : "radio3", checked : true },
{ value : 4, text : "radio4" }
];
function App() {
return (
<RadioGroup radios={radios} name="group1"/>
);
}
CheckBox.jsx
import { useState } from "react";
84 / 158
function handlerChange(event) {
setState({checked : event.target.checked});
setInfo(info + ' - ' + event.target.value )
}
return (
<label>
<input type="checkbox"
value={props.value}
checked={state.checked}
onChange={handlerChange.bind(this)} />
<span>{props.text}</span><br/>
{/* <p>{info}</p> */}
</label>
)
}
return (
<div>{
props.checkboxes.map((checkbox, index) => {
return (
<CheckBox key={index}
text={checkbox.text}
value={checkbox.value}
checked={checkbox.checked}
/>)}
)}
</div>
)
}
var checkboxes = [
{ value : 1, text : "check1" },
{ value : 2, text : "check2", checked : true },
{ value : 3, text : "check3", checked : true },
{ value : 4, text : "check4" }
];
function App() {
return (
<CheckBoxGroup checkboxes={checkboxes} />
);
}
CheckBox.jsx
import { useState } from "react";
function handlerChange(event) {
setState({checked : event.target.checked});
const obj = {value:props.value, text:props.text,
checked:state.checked};
if (!state.checked){
props.ajouter(obj)
} else {
props.supprimer(obj);
86 / 158
}
}
return (
<label>
<input type="checkbox"
value={props.value}
checked={state.checked}
onChange={handlerChange.bind(this)} />
<span>{props.text}</span><br/>
{/* <p>{info}</p> */}
</label>
)
}
CheckBoxGroup.jsx
import { useState } from "react";
import CheckBox from "./CheckBox";
return (
<>
<div>{
props.checkboxes.map((checkbox, index) => {
return (
<CheckBox key={index}
text={checkbox.text}
value={checkbox.value}
checked={checkbox.checked}
ajouter={ajouter}
supprimer={supprimer}
87 / 158
/>)}
)}
</div>
<ul>
{T.map((o) =>
<li key={o.value}>{o.text}</li>
)}
</ul>
</>
)
}
App.js
import CheckBoxGroup from "./components/CheckBoxGroup";
var checkboxes = [
{ value : 1, text : "check1" },
{ value : 2, text : "check2", checked : true },
{ value : 3, text : "check3", checked : true },
{ value : 4, text : "check4" }
];
function App() {
return (
<CheckBoxGroup checkboxes={checkboxes} />
);
}
Affichage de départ :
88 / 158
CheckBoxGroup.jsx
import { useState, useEffect } from "react";
import CheckBox from "./CheckBox";
return (
<>
<div>{
props.checkboxes.map((checkbox, index) => {
return (
<CheckBox key={index}
text={checkbox.text}
value={checkbox.value}
checked={checkbox.checked}
ajouter={ajouter}
supprimer={supprimer}
/>)}
)}
</div>
<ul>
{T.map((o) =>
<li key={o.value}>{o.text}</li>
)}
</ul>
</>
)
}
89 / 158
10.6 Exercice de synthèse (seance10-2-travaux-pratiques)
Inscription.jsx
import { useState } from "react"
function Inscription () {
return (
<div>
<h1>Inscription</h1>
<form>
<label>L'identifiant : <input type="text"
/></label>
<br/>
<label>Mot de passe : <input type="text"
/></label>
<br/>
90 / 158
<label>Date naissance : <input type="date"
/></label>
<br/>
<label>Genre : <input type="radio"
value="homme"/>Homme<input type="radio"
value="homme"/>Femme</label>
<br/>
<label>Loisir : <input type="checkbox"
/>Sport<input type="checkbox" />Lecture<input
type="checkbox" />Musique</label>
<br/>
<label>Photo : <input type="file" /></label>
<br/><br/>
<input type="button" value="S'inscrire"/>
</form>
</div>
);
}
function App() {
return (
<div>
<Inscription />
</div>
);
}
UseContext Hook :
Avec useState :
91 / 158
App.js
import { useState } from "react";
import Login from "./components/Login";
import User from "./components/User";
function App() {
const [username, setUsername] = useState('')
return (
<div>
<Login setUsername = {setUsername} />
<User username = {username} />
</div>
);
}
Login.jsx
function Login ({ setUsername }) {
return (
<input
onChange={(event) => {
setUsername(event.target.value);
}} />
)
}
User.jsx
function User ( { username }) {
return (
<div>
<h1>User: {username}</h1>
92 / 158
</div>
)
}
Avec useContext :
App.js
import { useState, createContext } from "react";
import Login from "./components/Login";
import User from "./components/User";
function App() {
const [username, setUsername] = useState('')
return (
<AppContext.Provider value={{username, setUsername}}>
<Login /><User />
</AppContext.Provider>
);
}
Login.jsx
import { useContext } from "react";
import { AppContext } from "../App";
function Login () {
return (
<input
onChange={(event) => {
setUsername(event.target.value);
}} />
)
93 / 158
}
User.jsx
import { useContext } from "react";
import { AppContext } from "../App";
function User () {
return (
<div>
<h1>User: {username}</h1>
</div>
)
}
axios.get('https://jsonplaceholder.typicode.com/users')
.then((res)=>{setUsers(res.data)})
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => {return response.json()})
.then((data) => setUsers(data))
94 / 158
Séance 13 : React Rooter
Step 2: Change your directory and enter your main folder charting as :
cd myreactapp
Example :
App.js
import {BrowserRouter as Router, Route, Routes,Link, Outlet}
from 'react-router-dom';
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from './pages/Contact';
import NoPage from './pages/NoPage';
// import {Home, About, Contact, NoPage} from './pages'
function App() {
return (
95 / 158
<Router>
<ul>
<li><Link to="/Home">Home</Link></li>
<li><Link to="/About">About</Link></li>
<li><Link to="/Contact">Contact</Link></li>
</ul>
<hr/>
<Routes >
<Route path="Home" element={<Home />} />
<Route path="About" element={<About />} />
<Route path="Contact" element={<Contact />} />
<Route path="*" element={<NoPage />} />
</Routes>
</Router>
);
}
Home.js
const Home = () => {
return (
<div>
<h2>Home</h2>
</div>
);
};
About.js
const About = () => {
return (
<div>
<h2>About</h2>
</div>
);
};
96 / 158
Contact.js
const Contact = () => {
return <h2>Contact Me</h2>;
};
NoPage.js
const NoPage = () => {
return <h1>404</h1>;
};
Liens : 1 - https://www.geeksforgeeks.org/reactjs-router/
2 - https://velopert.com/3417
97 / 158
// import {Home, About, Contact, NoPage} from './pages'
function App() {
return (
<Router>
<ul>
<li><Link to="/Home">Home</Link></li>
<li><Link to="/About">About</Link></li>
<li><Link to="/Contact">Contact</Link></li>
<li><Link to="/Posts">Posts</Link></li>
</ul>
<hr/>
<Routes >
<Route path="Home" element={<Home />} />
<Route path="About" element={<About />} />
<Route path="Contact" element={<Contact />} />
<Route path="Posts" element={<Posts />} />
<Route path="*" element={<NoPage />} />
</Routes>
</Router>
);
}
Séance 16
Concevoir une application avec Redux
cd myreactapp
99 / 158
Sans redux :
Avec redux :
100 / 158
Exemple : Sans Redux
components/Article.jsx
const Article = ({ article }) => (
<div className="article">
<h1>{article.title}</h1>
<p>{article.body}</p>
101 / 158
</div>
)
return (
<form onSubmit={addNewArticle} className="add-
article">
<input
type="text"
id="title"
placeholder="Title"
onChange={handleArticleData}
/>
<input
type="text"
id="body"
placeholder="Body"
onChange={handleArticleData}
/><br/>
<button>Add article</button>
</form>
)
}
102 / 158
export default AddArticle;
components/Articles.jsx
import React, { useState } from "react"
import Article from "../components/Article"
import AddArticle from "../components/AddArticle"
return (
<div>
<AddArticle saveArticle={saveArticle} />
{articles.map(article => (
<Article key={article.id} article={article} />
))}
</div>
)
}
function App() {
return (
<div>
<Articles />
</div>
103 / 158
)
components/Article.jsx
const Article = ({ article }) => (
<div className="article">
<h1>{article.title}</h1>
<p>{article.body}</p>
</div>
)
104 / 158
const handleArticleData = e => {
setArticle({
...article,
[e.target.id]: e.target.value,
})
}
const addNewArticle = e => {
e.preventDefault()
saveArticle(article)
}
return (
<form onSubmit={addNewArticle} className="add-
article">
<input
type="text"
id="title"
placeholder="Title"
onChange={handleArticleData}
/>
<input
type="text"
id="body"
placeholder="Body"
onChange={handleArticleData}
/><br/>
<button>Add article</button>
</form>
)
}
105 / 158
import AddArticle from "../components/AddArticle"
import { addArticle } from "../store/actionCreators"
export default
connect(mapStateToProps,mapDispatchToProps)(Articles);
App.js
import React from "react"
import Articles from "./components/Articles";
import { Provider} from "react-redux";
import { legacy_createStore } from "redux";
import reducer from "./store/reducer";
function App() {
const store = legacy_createStore(reducer)
return (
<Provider store={store}>
<Articles />
106 / 158
</Provider>
)
}
var k = 3;
const initialState = {
articles: [
{ id: 1, title: "post 1", body: "Body1 body1 body1" },
{ id: 2, title: "post 2", body: "Body2 body2 body2" },
],
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case actionTypes.ADD_ARTICLE:
const newArticle = {
id: ++k,
title: action.article.title,
body: action.article.body
}
return {
state,
articles: state.articles.concat(newArticle),
}
}
return state
}
store/actionCreators.js
import * as actionTypes from "../store/actionTypes"
107 / 158
}
}
store/actionTypes.js
export const ADD_ARTICLE = "ADD_ARTICLE" ;
Liens : https://perso-laris.univ-angers.fr/~lhommeau/teaching/HTML5/td/td5_react/
Suppression d’article :
components/Article.jsx
const Article = ({ article, removeArt }) => {
return (
<div className="article">
<h1>{article.title}</h1>
108 / 158
<p>{article.body}</p>
<button onClick={supprimerArt}>Supprimer</button>
</div>
)
}
export default Article;
components/AddArticle.jsx
import React, { useState } from "react"
return (
<form onSubmit={addNewArticle} className="add-
article">
<input
type="text"
id="title"
placeholder="Title"
onChange={handleArticleData}
/>
<input
type="text"
id="body"
placeholder="Body"
onChange={handleArticleData}
/><br/>
<button>Add article</button>
109 / 158
</form>
)
}
components/Articles.jsx
import { connect } from "react-redux"
import Article from "../components/Article"
import AddArticle from "../components/AddArticle"
import { addArticle,removeArticle } from
"../store/actionCreators"
export default
connect(mapStateToProps,mapDispatchToProps)(Articles);
110 / 158
App.js
import Articles from "./components/Articles";
import { Provider} from "react-redux";
import { legacy_createStore } from "redux";
import reducer from "./store/reducer";
function App() {
const store = legacy_createStore(reducer);
return (
<Provider store={store}>
<Articles />
</Provider>
)
}
var k = 3;
const initialState = {
articles: [
{ id: 1, title: "post 1", body: "Body1 body1 body1" },
{ id: 2, title: "post 2", body: "Body2 body2 body2" },
],
}
111 / 158
case actionTypes.REMOVE_ARTICLE:
return {
state,
articles: state.articles.filter((art) =>
art.id!==action.indice),
}
}
return state
}
store/actionCreators.js
import * as actionTypes from "./actionTypes"
Exemple 2 : Compteur.
112 / 158
store/reducer.js
const initialState = {num:0}
App.js
import { Provider } from "react-redux"
import { legacy_createStore } from "redux"
import reducer from "./store/reducer";
import Compteur from "./components/Compteur";
113 / 158
function App() {
return (
<Provider store={store}>
<Compteur />
</Provider>
);
}
return (
<div>
<p>{num}</p>
<button onClick={() => dispatch({type :
"Incrementer"})}>Incrémenter</button>
<button onClick={() => dispatch({type :
"Decrementer"})}>Decrémenter</button>
<button onClick={() => dispatch({type :
"Reset"})}>Reset</button>
</div>
)
}
typeActions.js
export const ADD_FRUIT='ADD_FRUIT'
export const REMOVE_ALL_FRUITS='REMOVE_ALL_FRUITS'
115 / 158
actionsFruit.js
import * as type from '../store/typeActions'
116 / 158
ListFruits.js
import {connect} from 'react-redux'
import { addFruit, viderFruit } from '../store/actionsFruit'
function ListFruits(props){
function mapStateToProps(state){
return {fruits:state.fruits}
}
function Fruiterie(props){
const [nomFruit,setNomFruit]=useState('')
117 / 158
return(<div className='container'>
<label htmlFor='fruit'> fruit : </label><input
onChange={(e)=>setNomFruit(e.target.value) }
id='fruit' value={nomFruit} />
<button onClick={()=>
{props.ajouterFruit(nomFruit);setNomFruit('')}}>
Ajouter</button>
<ListFruits/>
<button onClick={()=>
props.viderList()}>vider liste</button>
</div>)
}
function mapDispatchToProps(dispatch){
return {
ajouterFruit:function(myfruit){
dispatch(addFruit(myfruit))
},
viderList:function(){dispatch(viderFruit())}
}
}
function App() {
return (
<Provider store={store}>
<Fruiterie />
</Provider>
);
}
118 / 158
export default App;
index.css
.container{
margin:0;
margin-top:20px ;
padding: 8px;
width: 50%;
max-width: 300px;
border: 1px solid blueviolet;
background-color: antiquewhite;
box-shadow: 4px 4px rgb(232, 200, 81);
}
.fruits{
margin:20px;
padding: 8px;
width: 260px;
max-width: 160px;
background-color: rgb(221, 208, 247);
border:1px solid rgb(14, 19, 33)
}
typeActions.js
export const ADD_FRUIT='ADD_FRUIT'
export const REMOVE_FRUIT='REMOVE_FRUIT'
export const REMOVE_ALL_FRUITS='REMOVE_ALL_FRUITS'
actionsFruit.js
import * as type from '../store/typeActions'
119 / 158
export function addFruit(myFruit){
return({
type:type.ADD_FRUIT,
fruit:myFruit
})
}
reducerFruits.js
import * as type from '../store/typeActions'
const initialeState={
fruits:[]
}
function ListFruits(props){
function mapStateToProps(state){
return {fruits:state.fruits}
}
function mapDispatchToProps(dispatch){
return {
supprimerFruit:function(index){
dispatch(removeFruit(index))
}
}
}
121 / 158
export default
connect(mapStateToProps,mapDispatchToProps)(ListFruits)
122 / 158
typeActions.js
export const ADD_FRUIT='ADD_FRUIT'
export const REMOVE_ALL_FRUITS='REMOVE_ALL_FRUITS'
actionsFruit.js
import * as type from '../store/typeActions'
const initialeState={
fruits:[]
}
123 / 158
}
}
ListFruits.js
import {useSelector, useDispatch} from 'react-redux'
import { removeFruit } from '../store/actionsFruit'
function ListFruits(){
const fruits=useSelector(data=>data.fruits)
const dispatch = useDispatch()
function Fruiterie(){
const [nomFruit,setNomFruit]=useState('')
const dispatch = useDispatch()
return(<div className='container'>
<label htmlFor='fruit'> fruit : </label>
<input onChange={(e)=>setNomFruit(e.target.value)
}
id='fruit' value={nomFruit} />
<button
onClick={()=>{dispatch(addFruit(nomFruit));
124 / 158
setNomFruit('')}}>Ajouter</button>
<ListFruits/>
<button onClick={()=>dispatch(viderFruit())}>vider
liste</button>
</div>)
}
function App() {
return (
<Provider store={store}>
<Fruiterie />
</Provider>
);
}
.fruits{
margin:20px;
125 / 158
padding: 8px;
width: 260px;
max-width: 160px;
background-color: rgb(221, 208, 247);
border:1px solid rgb(14, 19, 33)
}
Port 8000 parceque le port 3000 est utilise par le serveur react.
126 / 158
Add :
axios.get('http://localhost:8000/fruits').then((res) =>
setFruits(res.data))
axios.put('http://localhost:8000/fruits/'+editID, {id:
editID,name: uname,price: uprice})
.then(() => {setEditID(-1)})
axios.delete('http://localhost:8000/fruits/'+id)
Table.jsx
import axios from 'axios'
import { useEffect, useState, location } from 'react'
127 / 158
function Table () {
const [fruits, setFruits] = useState([])
const [name, setName] = useState()
const [price, setPrice] = useState()
const [editID, setEditID] = useState(-1)
const [uname, setUname] = useState()
const [uprice, setUprice] = useState()
useEffect(()=> {
axios.get('http://localhost:8000/fruits').then((res) =>
setFruits(res.data))
})
return (
128 / 158
<div>
<div>
<form onSubmit={handleSubmit}>
<input type="text" placeholder='Enter Name'
onChange={e => setName(e.target.value)}/>
<input type="text" placeholder='Enter Price'
onChange={e => setPrice(e.target.value)}/>
<button>Add</button>
</form>
</div>
<table>
<thead>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Action</th>
</thead>
<tbody>
{
fruits.map((fruit,index) => (
fruit.id === editID?
<tr>
<td>{fruit.id}</td>
<td><input type='text'
value={uname} onChange={e => setUname(e.target.value)}/></td>
<td><input type='text'
value={uprice} onChange={e => setUprice(e.target.value)} /></td>
<td><button
onClick={handleUpdate}>Update</button></td>
</tr>
:
<tr key={index}>
<td>{fruit.id}</td>
<td>{fruit.name}</td>
<td>{fruit.price}</td>
<td>
<button onClick={()=>
handleEdit(fruit.id)}>Edit</button>
<button onClick={()=>
handleDelete(fruit.id)}>Delete</button>
</td>
129 / 158
</tr>
))
}
</tbody>
</table>
</div>
)
}
App.js
import Table from "./Table";
function App() {
return (
<div>
<Table />
</div>
);
}
index.css
table {
border: 1px solid black;
border-collapse: collapse ;
width: 400px;
text-align: center;
}
th {
background-color: lightgreen;
}
tr {
border-bottom: 1px solid black;
background-color: lightblue;
}
130 / 158
th, td {
padding: 5px;
}
form {
margin-bottom: 10px;
}
form input {
width: 110px;
padding: 5px;
}
form button {
width: 10%;
padding: 5px;
}
tbody input {
width: 80px;
}
data/db.json
{
"fruits": [
{
"id": "1",
"name": "Orange",
"price": 10
},
{
"id": "2",
"name": "Apple",
"price": 12
},
{
"id": "3",
"name": "Kiwi",
"price": "20"
}
]
131 / 158
}
Utilisation de composants
AddFruit.jsx
import axios from "axios"
import { useState } from "react"
function AddFruit(props) {
const [name, setName] = useState()
const [price, setPrice] = useState()
132 / 158
return (
<div>
<form onSubmit={handleSubmit}>
<input type="text" placeholder='Enter name'
onChange={(e) => setName(e.target.value)}/>
<input type="text" placeholder='Enter price'
onChange={(e) => setPrice(e.target.value)}/>
<button>Add</button>
</form>
</div>
)
}
ListHeader.jsx
function ListHeader () {
return (
<>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Action</th>
</>
)
}
LigneFruit.jsx
function LigneFruit (props) {
return (
<tr key={props.index}>
<td>{props.fruit.id}</td>
<td>{props.fruit.name}</td>
<td>{props.fruit.price}</td>
<td><button onClick={(e)=>
133 / 158
handleEdit(props.fruit.id)}>Edit</button><button>Delete</button></td>
</tr>
)
}
EditFruit.jsx
import axios, { axios } from 'axios'
import { useState} from 'react'
return (
<tr key={props.index}>
<td>{props.fruit.id}</td>
<td><input type="text" value={props.fruit.name}
onChange={(e) => setUname(e.target.value)}/></td>
<td><input type="text" value={props.fruit.price}
onChange={(e) => setUprice(e.target.value)}/></td>
<td><button
onClick={(e)=>handleUpdate(props.fruit.id)}>Update</button></td>
</tr>
)
}
Table.jsx
import axios from 'axios'
import { useState,useEffect} from 'react'
import AddFruit from './components/AddFruit'
import ListHeader from './components/ListHeader'
import LigneFruit from './components/LigneFruit'
import EditFruit from './components/EditFruit'
134 / 158
function Table () {
const [fruits, setFruits] = useState([])
const [editID, setEditID] = useState(-1)
useEffect(()=> {
axios.get('http://localhost:3000/fruits')
.then(res => setFruits(res.data))
})
return (
<div>
<AddFruit fruits={fruits}/>
<table>
<thead>
<ListHeader />
</thead>
<tbody>
{fruits.map((fruit,index) => (
editID === fruit.id?
<EditFruit fruit={fruit} index={index}
setEditId={setEditID}/>
:
<LigneFruit fruit={fruit} index={index}
setEditId={setEditID}/>
))}
</tbody>
</table>
</div>
)
}
App.js
import Table from "./Table";
function App() {
return (
<div>
<Table />
135 / 158
</div>
);
}
store/typeActions
export const ADD_FRUIT='ADD_FRUIT'
export const REMOVE_FRUIT='REMOVE_FRUIT'
export const UPDATE_FRUIT='UPDATE_FRUIT'
export const FIND_FRUIT='FIND_FRUIT'
export const REMOVE_ALL_FRUITS='REMOVE_ALL_FRUITS'
store/actionsFruit
import * as type from './typeActions'
136 / 158
export function addFruit(myFruit){
return({
type:type.ADD_FRUIT,
fruit:myFruit
})
}
const initialeState={
fruits:[
{
137 / 158
"id": "1",
"name": "Orange",
"price": 10
},
{
"id": "2",
"name": "Apple",
"price": 12
}
]
}
let id = 2
function AddFruit() {
const [name, setName] = useState()
const [price, setPrice] = useState()
138 / 158
const handleSubmit = (event) => {
event.preventDefault()
dispatch(addFruit({id:++id, name:name, price:
price}))
}
return (
<div className="fruits">
<form onSubmit={handleSubmit}>
<input type="text" placeholder='Enter name'
onChange={(e) => setName(e.target.value)}/>
<input type="text" placeholder='Enter price'
onChange={(e) => setPrice(e.target.value)}/>
<button>Add</button>
</form>
</div>
)
}
function ListFruit () {
const fruits = useSelector(data => data.fruits)
const dispatch = useDispatch()
return (
<div className="fruits">
<table>
<thead>
<th>ID</th>
139 / 158
<th>Name</th>
<th>Price</th>
<th>Action</th>
</thead>
<tbody>
{
fruits.map((fruit,index) => (
<tr key={fruit.id}>
<td>{fruit.id}</td>
<td>{fruit.name}</td>
<td>{fruit.price}</td>
<td>
<button>Edit</button>
<button onClick={(e) =>
handleDelete(fruit.id)}>Delete</button>
</td>
</tr>
))
}
</tbody>
</table>
</div>
)
}
function Fruiterie () {
return (
<div className='container'>
<AddFruit />
<ListFruit />
</div>
)
}
140 / 158
export default Fruiterie;
function App() {
index.css
.container{
margin:0;
margin-top:20px ;
padding: 8px;
width: 440px;
max-width: 500px;
border: 1px solid blueviolet;
background-color: antiquewhite;
box-shadow: 4px 4px rgb(232, 200, 81);
}
.fruits{
margin:20px;
padding: 8px;
width: 400px;
max-width: 420px;
background-color: rgb(221, 208, 247);
border:1px solid rgb(14, 19, 33)
141 / 158
}
table {
border: 1px solid black;
border-collapse: collapse ;
width: 400px;
text-align: center;
}
th {
background-color: lightgreen;
}
tr {
border-bottom: 1px solid black;
background-color: lightblue;
}
th, td {
padding: 5px;
}
form {
margin-bottom: 10px;
}
form input {
width: 110px;
padding: 5px;
}
form button {
width: 10%;
padding: 5px;
}
tbody input {
width: 80px;
}
142 / 158
Synthèse : CRUD avec Redux Toolkit
GroupeSlice.js
import { createSlice } from "@reduxjs/toolkit"
const initState = {
dbGroupes : [
{id:1,nom:"FS201"},
{id:2,nom:"FS202"},
{id:3,nom:"FS205"},
{id:4,nom:"FS206"},
]
}
143 / 158
state.dbGroupes= [...state.dbGroupes,
action.payload] },
deleteGroupe :(state,action)=>{
state.dbGroupes.splice(action.payload,1)},
UpdateGroupe: (state, action)=>{
state.dbGroupes.map(grp =>
{if(grp.id==action.payload.id) grp.nom =
action.payload.nom;})
},
},
})
Store.js
import { configureStore } from "@reduxjs/toolkit";
import GroupeSlice from "./GroupeSlice";
const store=configureStore({
reducer:{
Groupe:GroupeSlice,
},
})
function Groupe(){
const [grId, setGrId] =useState();
const [nomg, setnomg] = useState();
let listGroupe = useSelector(state =>
state.Groupe.dbGroupes);
144 / 158
let dispatch = useDispatch();
return (
<div>
<center>
<input type="text" placeholder="id" value={grId}
onChange={(e)=>setGrId(e.target.value)} />
<input type="text" placeholder="Marque" value={nomg}
onChange={(e)=>setnomg(e.target.value)} />
App.js
import React from 'react';
import './index.css';
function App() {
return (
<Provider store={store}>
<Groupe/>
</Provider>
);
}
146 / 158
cd react_crud
npm start
147 / 158
https://www.geeksforgeeks.org/how-to-do-crud-operations-in-reactjs/
148 / 158
// Filename - App.js
function App() {
return (
<div className="App">
<h1 className="geeks">GeeksforGeeks </h1>
<h3>CRUD App</h3>
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route
path="/create"
element={<Create />}
/>
<Route
path="/edit"
element={<Edit />}
/>
</Routes>
</Router>
</div>
);
}
// Filename - components/array.js
// Filename - components/Create.js
150 / 158
import React, { useState } from "react";
import { Button, Form } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
import array from "./array";
import { v4 as uuid } from "uuid";
import { Link, useNavigate } from "react-router-dom";
function Create() {
// Making usestate for setting and
// fetching a value in jsx
const [name, setname] = useState("");
const [age, setage] = useState("");
return (
<div>
<Form
className="d-grid gap-2"
style={{ margin: "5rem" }}
>
{/* Fetching a value from input textfirld
in a setname using usestate*/}
<Form.Group
className="mb-3"
controlId="formBasicName"
>
<Form.Control
onChange={(e) =>
setname(e.target.value)
}
type="text"
placeholder="Enter Name"
required
/>
</Form.Group>
151 / 158
controlId="formBasicAge"
>
<Form.Control
onChange={(e) =>
setage(e.target.value)
}
type="number"
placeholder="Age"
required
/>
</Form.Group>
// Filename - components/Home.js
function Home() {
let history = useNavigate();
152 / 158
.indexOf(id);
return (
<div style={{ margin: "5rem" }}>
<Table striped bordered hover size="sm">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
{/* Mapping though every element
in the array and showing the
data in the form of table */}
{array.map((item) => {
return (
<tr>
<td>{item.Name}</td>
<td>{item.Age}</td>
153 / 158
})}
</tbody>
</Table>
// Filename - Edit.js
import React, { useEffect, useState } from "react";
import { Button, Form } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
import array from "./array";
import { Link } from "react-router-dom";
import { useNavigate } from "react-router-dom";
function Edit() {
// Here usestate has been used in order
// to set and get values from the jsx
const [name, setname] = useState("");
const [age, setage] = useState("");
const [id, setid] = useState("");
154 / 158
a.Age = age;
return (
<div>
<Form
className="d-grid gap-2"
style={{ margin: "5rem" }}
>
{/* setting a name from the
input textfiled */}
<Form.Group
className="mb-3"
controlId="formBasicEmail"
>
<Form.Control
value={name}
onChange={(e) =>
setname(e.target.value)
}
type="text"
placeholder="Enter Name"
/>
</Form.Group>
155 / 158
{/* Redirecting to main page after editing */}
<Link className="d-grid gap-2" to="/">
<Button variant="warning" size="lg">
Home
</Button>
</Link>
</Form>
</div>
);
}
/* App.css */
.App {
text-align: center;
}
.geeks {
color: green;
}
npm i json-server
156 / 158
**** Commandes Json-server :
Liens:
https://react.dev/learn/updating-arrays-in-state
157 / 158
158 / 158