0% found this document useful (0 votes)
15 views158 pages

Guide de Cours Et TPs - M204 - React JS - Nov 2024

This document serves as a comprehensive guide to React JS, covering its fundamentals, environment setup, and key features such as ES6 syntax, components, and props. It includes practical examples and exercises to reinforce learning, focusing on important concepts like classes, arrow functions, array methods, destructuring, and modules. The guide is structured to help learners build user interfaces effectively using React, with a step-by-step approach to creating applications.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views158 pages

Guide de Cours Et TPs - M204 - React JS - Nov 2024

This document serves as a comprehensive guide to React JS, covering its fundamentals, environment setup, and key features such as ES6 syntax, components, and props. It includes practical examples and exercises to reinforce learning, focusing on important concepts like classes, arrow functions, array methods, destructuring, and modules. The guide is structured to help learners build user interfaces effectively using React, with a step-by-step approach to creating applications.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 158

Guide de cours et TPs

L’essentiel de React JS

React JS ‫المختصر المفيد في لغة‬


Préparé par :
M. Hamid Mask

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.

What is React? (w3school)


React, sometimes referred to as a frontend JavaScript framework, is a
JavaScript library created by Facebook.
React is a tool for building UI components.

I. React Environnement Setup.


1. Manually setting up all the things using webpack and babel.
2. Using the create-react-app command.

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.

II - Why Should I Learn ES6?


React uses ES6, and you should be familiar with some of the new features
like:
 Classes
 Arrow Functions
 Variables (let, const, var)
 Array Methods like .map()
 Destructuring
 Modules
 Ternary Operator
 Spread Operator

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;
}
}

const p1 = new Personne("Ramzi",23);


const p2 = new Personne("Karam",21);

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;
}
}

const s1 = new Stagiaire("Ramzi",23,'dev web');


const s2 = new Stagiaire("Karam",21,'dev mobile');

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));

With Arrow Function :


const Somme = (a,b) => a + b;

document.write(Somme(30,50));

Arrow Function Without Parentheses :


const Double = x => 2*x;

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 },
];

const noms=personnes.map(function(pers){return pers.nom})


document.write(noms);

 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.

const personAgés = personnes.filter((pers) => pers.estMember).

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);

const pers1 = personnes.find((pers) => pers.age == 50);

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,' ',v2,' ',v3);

Here is the new way of assigning array items to a variable:


// new way : with destructuring:
const [v1, v2, v3] = voitures;

document.write(v1,' ',v2,' ',v3);

const [v1,, v3] = voitures;

document.write(v1,' ',v3);

const [v1, v3] = voitures;

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;

return [add, subtract, multiply, divide];


}

const [add, subtract, multiply, divide] = calculate(4, 2);


document.write(add,' ',subtract,' ',multiply,' ',divide);

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));

function myVehicle({type, color, brand, model}) {


const message = 'My ' + type + ' is a ' + color + ' ' +
brand + ' ' + model + '.';
return message;
}

We can even destructure deeply nested objects


const vehicleOne = {
brand: 'Ford',
model: 'Mustang',
type: 'car',
year: 2021,
color: 'red',
registration: {
city: 'Houston',
state: 'Texas',
country: 'USA'
}
}

myVehicle(vehicleOne);
10 / 158
document.write(myVehicle(vehicleOne));

function myVehicle({ model, registration: { state } }) {


const message = 'My ' + model + ' is registered in ' + state
+ '.';
return message;
}

Spread Operator
const T1 = [1, 2, 3];
const T2 = [4, 5, 6];
const T = [...T1, ...T2];

document.write(T)

const numbers = [1, 2, 3, 4, 5, 6];


const [one, two, ...rest] = numbers;

document.write(rest)

 Combine these two objects:


const myVehicle = {
brand: 'Ford',
model: 'Mustang',
color: 'red'
}

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';
}
}

export {name, age, Som, Personne};

12 / 158
index.js
import { name,age, Som, Personne } from "./personne.js";

console.log(name + ' a ' + age + 'ans');


// Use Som function
// Use Personne class

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;

export function Som(a,b) {


return a + b;
}

export default class Personne{


constructor(name, age) {
this.name = name;
this.age = age;
}

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";

console.log(name + ' a ' + age + 'ans');


// Use Som function
// Use Personne class

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'}
];

Créer la pure fonction qui permet d’ajouter une inscription

Fusion de deux objets


// Fusion de deux objets
const obj1 = {id:1,nom:"Falah"};
const obj2 = {prenom:"Walid",age:20};
// console.log(Object.assign({}, obj1,
{prenom:"Walid",age:20}));
console.log({...obj1,...obj2});

Notion de Composant
1. Component.

const App = () => {


const nom = 'Walid';

return (
<div className="App">
<h1>Hello, {nom}!</h1>
</div>
);
}

export default App;


Hello, Walid!

const App = () => {


const nom = 'Walid';

14 / 158
const isNameShown = true;
return (
<div className="App">
<h1>Hello, {isNameShown? nom : 'someone'}!</h1>
</div>
);
}

export default App;


Hello, Walid!

const App = () => {

return (
<div className="App">
<h1>{2 + 4}</h1>
</div>
);
}

export default App;


6

2. Exemples de composant et props :


Exemple 1 :
import './App.css';

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>
);
}

export default App;

Exemple 2 : Avec props :


import './App.css';

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>
);
}

export default App;

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;

B.jsx (ou B.js) :


function B(props){
return (
<div>
<h1>Article : {props.article.desi} coûte
{props.article.pu} dhs</h1>
</div>
)

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 App;

On peut se servir de la destructuration dans les composants A et B :


A.js
function A(props){

const {nom,ville} = props.client;


return (
<div>
<h1>Hello, {nom} tu habites {ville}</h1>
</div>
)
}

export default A;

18 / 158
B.js
function B(props){

const {desi,pu} = props.article;


return (
<div>
<h1>Article : {desi} coûte {pu} dhs</h1>
</div>
)
}

export default B;

Séance 4 : JSX
Créer une liste de cinq éléments en JSX
function App() {

var liste = <ul id="liste1" className="red">


<li> Element1 </li>
<li> Element2 </li>
<li> Element3 </li>
<li> Element4 </li>
<li> Element5 </li>
</ul>;

return (
<div>
{liste}
</div>
);
}

export default App;

Index.css
.red {
color : red;
}

19 / 158
function App() {

var liste = <ul id="liste1" style={{listStyleType:"none",


color:"red"}}>
<li> Element1 </li>
<li> Element2 </li>
<li> Element3 </li>
<li> Element4 </li>
<li> Element5 </li>
</ul>;

return (
<div>
{liste}
</div>
);
}

export default App;

function App() {

var color = "red";


var styleListe = { listStyleType:"none", color:color };
var liste = <ul id="liste1" style={styleListe}>
<li> Element1 </li>
<li> Element2 </li>
20 / 158
<li> Element3 </li>
<li> Element4 </li>
<li> Element5 </li>
</ul>;

return (
<div>
{liste}
</div>
);
}

export default App;

Utiliser un tableau d’elements :

function App() {

var color = "red";


var styleListe = { listStyleType:"none", color:color };
var elems =
["Element1","Element2","Element3","Element4","Element5"];
var liste = <ul id="liste1" style={styleListe}>
{
elems.map(function(elem,index){
return <li key={index}>{elem}</li>
})
}
</ul>;

return (
<div>
{liste}
</div>
);
}

export default App;

En utilisant un arrow function dans map :


elems.map((elem,index) => <li key={index}>{elem}</li>)

21 / 158
Séance 6 : Passage d’un Array dans props

Presentation.js (Composant Presentation)


function Presentation (props){
const {nom, prenom} = props.personne
return (
<div>
<h2>Salut {nom} {prenom}</h2>
<hr/>
<h3>Diplômes</h3>
<ul>
{props.diplomes.map((diplome) => (
<li>{diplome}</li>
))}
</ul>
</div>
)
}

export default Presentation;

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'}

const diplomes2 = ['Bac', 'Licence']


return (
<div className="App">
<Presentation personne={personne1} diplomes={diplomes1}
/>

22 / 158
<hr className='hr'/>
<Presentation personne={personne2} diplomes={diplomes2}
/>
</div>
);
}

export default App;

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

Presentation.js (Composant Presentation)


function Presentation (props){
const {id, nom, prenom,diplomes} = props.personne
return (
<div>
<h2>Salut {nom} {prenom}</h2>
<hr/>
<h3>Diplômes</h3>
<ul>
{diplomes.map((diplome) => (
<li>{diplome}</li>
))}
</ul>
</div>
)
}

export default Presentation;

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>
);
}

export default App;

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;
}

Séance 8 : Gestion des événements


Football.jsx
function Football() {
const shoot = () => {
alert("Great Shot!");
}

return (
<button onClick={shoot}>Take the shot!</button>
);
}

export default Football;

App.js
import './App.css';
import Football from './Football.jsx';

26 / 158
function App() {

return (
<div className="App">
<Football />
</div>
);
}

export default App;

Passing Arguments
Football.jsx
function Football() {
const shoot = (a) => {
alert(a);
}

return (
<button onClick={() => shoot("Goal!")}>Take the
shot!</button>
);
}

export default Football;

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>
);
}

export default Football;

TP Séance 4 : Cards

Component & style.


Exemple 1 : Card components (Vidéo Bro Code)
https://www.youtube.com/watch?v=yYiwxYqQ9vg&list=PLZPZq0r_RZOMQArzyI32mVndGBZ3D99XQ&index=2

Card.jsx (Composant Card)


function Card (props) {
return (
<div className="card">
<img className="card-image" src={props.image}

28 / 158
alt="Photo"></img>
<h2>{props.nom}</h2>
<p>{props.description}</p>
</div>
)

export default Card

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>
);
}

export default App;

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 )

Personne.jsx (Composant Personne)


function Produit(props){

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
)
}

export default Produit;

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>
);
}

export default App;

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;
}

Qu'est-ce qu'un hook ?


Un hook n'est ni plus, ni moins, qu'une fonction en JavaScript. Vous l'appelez comme une
fonction avec la possibilité de lui passer un ou plusieurs paramètres et cette fonction va vous
renvoyer un résultat. Cependant, un hook va suivre 2 règles fondamentales pour être utilisé.
Vous ne pouvez appeler un hook uniquement au plus haut niveau (la racine) de votre
fonction. Vous ne pourrez donc pas appeler de hook dans une instruction algorithmique
(boucle, structure conditionnel avec un if, etc... )
Appelez les hooks uniquement depuis des functional components. Vous ne devez pas
appeler un hook dans une fonction JavaSript classique excepté si c'est un hook personnalisé.
https://essential-dev-skills.com/reactjs/les-hooks/use-effect

React useState Hook


The React useState Hook allows us to track state in a function component.
State generally refers to data or properties that need to be tracking in an application.

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>
);
}

export default App;

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>
);
}

export default App;

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"
});

const updateColor = () => {


setVoiture(previousState => {
return { ...previousState, couleur: "blue"
}
});
}

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>
);
}

export default App;

React useEffect Hooks


The useEffect Hook allows you to perform side effects in your components.
Some examples of side effects are: fetching data, directly updating the DOM, and
timers.
useEffect accepts two arguments. The second argument is optional.
useEffect(<function>, <dependency>).

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>
</>
);
}

export default App;

Example 2 :
import { useState, useEffect} from "react";

function App() {
const [windowWidth, setwindowWidth] =
useState(window.innerWidth)

return (
<div>
{windowWidth}
</div>
);
}

export default App;

import { useState, useEffect} from "react";

function App() {
const [windowWidth, setwindowWidth] =
useState(window.innerWidth)

const Redim = () => {

38 / 158
setwindowWidth(window.innerWidth)
}

useEffect(() => {
window.addEventListener('resize', Redim)
}, [])

return (
<div>
{windowWidth}
</div>
);
}

export default App;

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>
);
}

export default App;

const App = () => {


const nom = null;
return (
<div className="App">
<h1>Hello {2 + 4}!</h1>
{nom ? (
<>
<h1>{nom}</h1>
</>
) : (
<>  Fragment
<h1>test</h1>
<h2>There is no name</h2>
</>
)}
</div>
);
40 / 158
}

export default App;


Hello 6!
Test
There is no name

Exemple :
const Person = () => {  This is a component
return (
<>
<h1>Name: Walid</h1>
<h2>Last Name: Alami</h2>
<h2>Age: 30</h2>
</>
)
}

const App = () => {


const nom = null;
return (
<div className="App">
<Person />
</div>
);
}

export default App;

const Person = () => {


return (
<>
<h1>Name: Walid</h1>
<h2>Last Name: Alami</h2>

41 / 158
<h2>Age: 30</h2>
</>
)
}

const App = () => {


const nom = null;
return (
<div className="App">
<Person />
<Person />
<Person />
<Person />
</div>
);
}

export default App;

3. Props.
const Person = (props) => {
return (
<>
<h1>Name: {props.name}</h1>
<h2>Last Name: {props.lastname}</h2>
<h2>Age: {props.age}</h2>
</>
)

42 / 158
}

const App = () => {


const nom = null;
return (
<div className="App">
<Person name='Walid' lastname='Alami' age={30}/>
<Person name="Rachid" lastname='Tazi' age={25}/>
</div>
);
}

export default App;

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';

const App = () => {


const [counter, setCounter] = useState(0);
return (
<div className="App">
<button onClick={() => setCounter((prevCount) => prevCount
- 1
)}>-
</button>
<h1>{counter}</h1>
<button onClick={() => setCounter((prevCount) => prevCount

43 / 158
+ 1

)}>+</button>
</div>
);
}

export default App;

The very important thing is that all of this is happening without a website
reload.

 Official React documentation (documentation officielle) :


https://legacy.reactjs.org/docs/getting-started.html

1. useEffect (second most important hook).

import { useState, useEffect } from 'react';


import './App.css';

const App = () => {


const [counter, setCounter] = useState(0);

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>
);
}

export default App;


useEffect allows us to do something on some kind of an effect or some
kind of an event so this code right here is going to be run as soon as the
page reloads.

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';

const App = () => {


const [counter, setCounter] = useState(0);

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:

import { useState, useEffect } from 'react';


import './App.css';

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>
);
}

export default App;

import { useState, useEffect } from 'react';


import './App.css';

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>
);
}

export default App;

Adding Forms in React


Just like in HTML, React uses forms to allow users to interact with the web page.
You add a form with React like any other element:

import './App.css';

function Form1() {
return (
<form>
<label>Enter your name:
<input type="text" />
</label>
</form>
)

47 / 158
}

const App = () => {


return (
<div className="App">
<Form1 />
<Form1 />
<Form1 />
</div>)
};

export default App;

Handling Forms
Use the useState Hook to manage the input:

Multiple Input Fields


import './App.css';

import { useState } from 'react';


import ReactDOM from 'react-dom/client';

function Form1() {
const [inputs, setInputs] = useState({});

const handleChange = (event) => {


const name = event.target.name;
const value = event.target.value;
setInputs(values => ({...values, [name]: value}))
}

const handleSubmit = (event) => {


event.preventDefault();
alert(inputs['username']);
alert(inputs['age']);
48 / 158
}

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>
)
}

const App = () => {


return (
<div className="App">
<Form1 />
</div>)
};

export default App;

Séance 8: Gestion des événements

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>&nbsp;&nbsp;&nbsp;&nbsp;<input
type="text"/>
</div>
<br/>
<div>
<label>Prenom:</label><input type="text"/>
</div>
<br/>
<button>Afficher</button>
<p>Information</p>
</>
)
}

export default Form1;

App.js

import './App.css';
import Inscription from './Inscription.jsx';

50 / 158
function App() {

return (
<div>
<Form1 />
</div>
);
}

export default App;

Inscription.jsx

import React, { useState } from "react";

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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input
type="text"
onChange={(e)=>{setNom(e.target.value.toUpperCase())}}/>
</div>
<br/>
<div>
<label>Prenom:</label>;&nbsp <input type="text"
onChange={(e)=>{setPrenom(e.target.value.toUpperCase())}}/>
</div>
<br/>
<button onClick={afficher}>Afficher</button>
<p>{information}</p>
</>
)
}

export default Inscription;


App.js
import './App.css';
import Inscription from './Inscription';

function App() {

return (
<div>
<Inscription />
</div>
);
}

export default App;

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(){

const [nom, setNom]=useState()


const [prenom, setPrenom]=useState()
const [T, setT]=useState([])

function ajouter(){
const personne = {id:++nextId, nom:nom, prenom:prenom}
setT([...T, personne])
}

return(
<>
<h2>Inscription</h2>
<div>
<label>Nom:</label>&nbsp;&nbsp;&nbsp;&nbsp;<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>
))}
</>
)
}

export default Inscription;

Travail à faire :
1- Affichage dans un tableau: <table></table>
2 - Affichage à l'aide d'un composant.

1 – Affichage dans un tableau :

54 / 158
Inscription.jsx
import React, { useState } from "react";

let nextId = 0;

function Inscription(){

const [nom, setNom]=useState()


const [prenom, setPrenom]=useState()
const [T, setT]=useState([])

function ajouter(){
const personne = {id:++nextId, nom:nom, prenom:prenom}
setT([...T, personne])
}

return(
<>
<h2>Inscription</h2>
<div>
<label>Nom:</label>&nbsp;&nbsp;&nbsp;&nbsp;<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>
</>
)
}

export default Inscription;

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;
}

 Avec bouton supprimer :

56 / 158
Inscription.jsx
import React, { useState } from "react";
import Personne from "./Personne";

let nextId = 0;

function Inscription(){

const [nom, setNom]=useState()


const [prenom, setPrenom]=useState()
const [T, setT]=useState([])

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>&nbsp;&nbsp;&nbsp;&nbsp;<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>

</>
)
}

export default Inscription;


Autre façon:
Inscription.jsx
import { useState } from "react";

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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text"
onChange={e => setNom(e.target.value.toUpperCase())}/>
</div>
<br/>
<div>
<label>Prenom :</label>&nbsp;<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;

2 – Affichage à l’aide d’un composant :

Personne.jsx
import './index.css'

function Personne (props) {


const {id, nom, prenom} = props.personne;

return (
<div className='personne'>
<h1>{id}</h1>
<h2>{nom}</h2>
<h3>{prenom}</h3>
</div>
)
}

export default Personne;

Inscription.jsx
import React, { useState } from "react";
import Personne from "./Personne";

let nextId = 0;

function Inscription(){

const [nom, setNom]=useState()


60 / 158
const [prenom, setPrenom]=useState()
const [T, setT]=useState([])

function ajouter(){
const personne = {id:++nextId, nom:nom, prenom:prenom}
setT([...T, personne])
}

return(
<>
<h2>Inscription</h2>
<div>
<label>Nom:</label>&nbsp;&nbsp;&nbsp;&nbsp;<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} />
))}
</>
)
}

export default Inscription;


index.css
h1,h2,h3 {
padding: 0%;
margin: 0%;
}

.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;
}

 Bouton supprimer dans le composant Personne :

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])
}

const supprimer = idP => setT(p => T.filter( p => p.id !=


idP))

return(
<>
<h2>Inscription</h2>
<div>
<label>Nom
:</label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text"
onChange={e => setNom(e.target.value.toUpperCase())}/>
</div>
<br/>
<div>
<label>Prenom :</label>&nbsp;<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
</>
)
}

export default Inscription;

8.3.2. Cycle de vie Composants.


 Cycle de vie Composants créer via classes
Composant life cycle est caractérisée par les méthodes optionnelles qu’on
peut définir dans un composant créé par une classe.
React est responsable de faire l’appel automatique de ces méthodes au
moment convenable (voir schéma) pendant le cycle de vie du composant.

import React from 'react'

export default class Compteur extends React.Component{


constructor(props) {
console.log("constructeur")
super(props)
this.state = {compteur:0}
this.incrementer=()=>{this.setState({compteur:
this.state.compteur+1})}
this.decrementer=()=>{this.setState({compteur:
this.state.compteur-1})}
}

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>
)
}
}

 Cycle de vie des Composants crés via fonction


Vous pouvez tirer parti du Hook useEffect pour obtenir les mêmes résultats
qu'avec les méthodes :

 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
);
}

export default App;

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>
)
}

export default ResultatList;

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.

Séance 9 : Personnaliser les composants React


9.1 Styliser les composants React (Inline CSS)

Bouton.js (Composant Bouton)


function Bouton() {
return (
<button style={{color:"blue", borderColor:"green",
padding:"10px", backgroundColor:"yellow" }}>Nom du
bouton</button>
);
}

export default Bouton;


App.js
import './App.css';
import Bouton from './Bouton';

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

export default App;

9.2 Styliser les composants React (Modules CSS : index.css)

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>
);
}

export default Bouton;

9.3 Composants stylisés


Installer des composants stylisés en utilisant npm :
npm install styled-components
Ensuite, ajouter cette importation :
import styled from 'styled-components'

Bouton.js (Composant stylé)


import styled from "styled-components";

const Bouton = styled.button`


color:blue;
border-color:green;
padding: 10px;
background-color:yellow;
`
export default Bouton;
` : Backtick (AltGr + 7)
App.js
import Bouton from "./components/Bouton";

function App() {
return (

71 / 158
<div>
<Bouton>Nom du bouton</Bouton>
</div>
);
}

export default App;

 Un autre exemple :

App.js
import styled from 'styled-components';

// Create a Title component that'll render an <h1> tag with


some styles
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: #BF4F74;
`;

// Create a Wrapper component that'll render a <section> tag


with some styles
const Wrapper = styled.section`
padding: 4em;
background: lightblue;
`;

function App() {
return (
<Wrapper>
<Title>
Hello World!
</Title>
</Wrapper>
);
72 / 158
}

export default App;

9.3 Affichage conditionnel


function App() {
return (
<Identification isLoggedIn={true}
/>
);
}
function App() {
return (
<Identification isLoggedIn={false}
/>
);
}

Connecte.js
function Connecte() {
return (
<h1>Bienvenue !</h1>
);
}

export default Connecte;

Anonymous.js
function Anonymous() {
return (
<h1>Veuillez vous inscrire.</h1>
);
}

export default Anonymous;

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 />;
}

export default Identification;

App.js
import Identification from "./components/Identification";

function App() {
return (
<Identification isLoggedIn={false} />
);
}

export default App;

Séance 10 : Créer des formulaires

10.1 Composants contrôlés

NameForm.js
import { useState } from "react";

const NameForm = () => {


const [nom, setNom] = useState('');
const [info, setInfo] = useState('');

const handleChange =(event)=>{


setNom(event.target.value);
}
74 / 158
const handleSubmit =(event)=>{
setInfo('Le nom a été soumis : ' + nom);
event.preventDefault();
}

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>
);
};

export default NameForm;


App.js
import NameForm from "./NameForm";

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

export default App;

10.2 Gérer les champs de saisie multilignes (Textarea)


Un champ de saisie multiligne se définit grâce à l’élément <textarea>.
Créons un composant <TextArea> qui «améliore» l’élément <textarea>
traditionnel.

75 / 158
TextArea.jsx
import { useState } from "react";

const TextArea = (props) => {

const [message, setMessage] = useState(props.value);


const handlerChange=(event)=>{
setMessage(event.target.value);
}

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>
);
};

export default TextArea;

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>
);
}

export default App;

10.3 Gérer les listes de sélection


Listes de sélection écrite en HTML :

Select.jsx
import { useState } from "react";

const Select = (props) => {


const [info, setInfo] = useState()

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>
);
};

export default Select;

import Select from "./components/Select";

const T = ["Element1", "Element2", "Element3", "Element4",


"Element5"]

function App() {
return (
<div className="App">
<Select options={T} />
</div>
);
}

export default App;

 Séléctionner et afficher la valeur :

Select.jsx
import { useState } from "react";

const Select = (props) => {

const [valeur, setvaleur] = useState()

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>
);
};

export default Select;

import Select from "./components/Select";

const T = ["Element1", "Element2", "Element3", "Element4",


"Element5"]

function App() {
return (
<div className="App">
<Select options={T} />
</div>
);
}

export default App;

10.4 Gérer les boutons radio

79 / 158
RadioGroup.jsx
import { useState } from "react";

const RadioGroup = (props) => {


const [valeur, setValeur] = useState()

const onOptionChange = e => {


setValeur(e.target.value)
}
return (
<div> {
props.radios.map((radio, index) => {
return (
<label key={index+1}>
<input type="radio"
value={radio.value}
name={props.name}
defaultChecked = {radio.checked}
onChange={onOptionChange}/>
<span>{radio.text}</span><br/>
</label>
)
}) }
<p>Selected option is : {valeur}</p>
</div>
);
};

export default RadioGroup;


App.js
import RadioGroup from "./components/RadioGroup";

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"/>
);
}

export default App;

 useEffect() : pour afficher la valeur du radio button par defaut

RadioGroup.jsx
import { useState, useEffect } from "react";

const RadioGroup = (props) => {


const [valeur, setValeur] = useState()

// pour afficher le radio button choisi par défaut


// [] pour que useEffect s'execute une seule fois
useEffect(() => {
const rb = props.radios.find(radio => radio.checked ==
true);
setValeur(rb.text)
}, [])

const onOptionChange = e => {


setValeur(e.target.value)
}

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>
);
};

export default RadioGroup;

 Utiliser deux composants RadioGroup et RadioBouton.

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>

)
}

export default RadioBouton;

RadioGroup.jsx
import { useState, useEffect } from "react";
import RadioBouton from "./RadioBouton";

const RadioGroup = (props) => {


const [valeur, setValeur] = useState()

// pour afficher le radio button choisi par défaut


// [] pour que useEffect s'execute une seule fois
useEffect(() => {
const rb = props.radios.find(radio => radio.checked ==
true);
setValeur(rb.text)
}, [])

const onOptionChange = v => {


setValeur(v)
}
return (
<div> {
props.radios.map((radio, index) => {
return (
<RadioBouton key={radio.value} text={radio.text}
name={props.name}
checked={radio.checked}
onOptionChange={onOptionChange} />
)
}) }
<p>Selected option is : {valeur}</p>

83 / 158
</div>
);
};

export default RadioGroup;


App.js
import RadioGroup from "./components/RadioGroup";

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"/>
);
}

export default App;

10.5 Gérer les cases à cocher

CheckBox.jsx
import { useState } from "react";

const CheckBox = (props) => {

const [state, setState] = useState({ checked :


props.checked || false })
const [info, setInfo] = useState('')

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>
)
}

export default CheckBox;


CheckBoxGroup.jsx
import CheckBox from "./CheckBox";

const CheckBoxGroup = (props) => {

return (
<div>{
props.checkboxes.map((checkbox, index) => {
return (
<CheckBox key={index}
text={checkbox.text}
value={checkbox.value}
checked={checkbox.checked}
/>)}
)}
</div>
)
}

export default CheckBoxGroup;


App.js
85 / 158
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} />
);
}

export default App;


 Avec affichage des cases cochées :

CheckBox.jsx
import { useState } from "react";

const CheckBox = (props) => {

const [state, setState] = useState({ checked : props.checked ||


false })

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>
)
}

export default CheckBox;

CheckBoxGroup.jsx
import { useState } from "react";
import CheckBox from "./CheckBox";

const CheckBoxGroup = (props) => {


const [T, setT] = useState([])

const ajouter = (obj) => {


setT([...T, obj])
}

const supprimer = (obj) => {


setT(T.filter((o) => o.value!==obj.value))
}

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>
</>
)
}

export default CheckBoxGroup;

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} />
);
}

export default App;

 Affichage de départ :

88 / 158
CheckBoxGroup.jsx
import { useState, useEffect } from "react";
import CheckBox from "./CheckBox";

const CheckBoxGroup = (props) => {


const [T, setT] = useState([])

useEffect (() => {


setT(props.checkboxes.filter((o) => o.checked === true))
}, [props.checkboxes])

const ajouter = (obj) => {


setT([...T, obj])
}

const supprimer = (obj) => {


setT(T.filter((o) => o.value!==obj.value))
}

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>
</>
)
}

export default CheckBoxGroup;

89 / 158
10.6 Exercice de synthèse (seance10-2-travaux-pratiques)

Inscription.jsx
import { useState } from "react"

function Inscription () {

const [id, setId] = useState()


const [pass, setPass] = useState()
const [dateNais, setDateNais] = useState()
const [ville, setVille] = useState()
const [genre, setGenre] = useState()
const [loisirs, setLoisirs] = useState([])
const [photo, setPhoto] = useState()

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>
);
}

export default Inscription;


App.jsx
import Inscription from "./components/Inscription";

function App() {

return (
<div>
<Inscription />
</div>
);
}

export default App;

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>
);
}

export default App;

Login.jsx
function Login ({ setUsername }) {

return (
<input
onChange={(event) => {
setUsername(event.target.value);
}} />
)
}

export default Login;

User.jsx
function User ( { username }) {

return (
<div>
<h1>User: {username}</h1>
92 / 158
</div>
)
}

export default User;

 Avec useContext :
App.js
import { useState, createContext } from "react";
import Login from "./components/Login";
import User from "./components/User";

export const AppContext = createContext(null);

function App() {
const [username, setUsername] = useState('')

return (
<AppContext.Provider value={{username, setUsername}}>
<Login /><User />
</AppContext.Provider>
);
}

export default App;

Login.jsx
import { useContext } from "react";
import { AppContext } from "../App";

function Login () {

const {setUsername} = useContext(AppContext);

return (
<input
onChange={(event) => {
setUsername(event.target.value);
}} />
)

93 / 158
}

export default Login;

User.jsx
import { useContext } from "react";
import { AppContext } from "../App";

function User () {

const {username} = useContext(AppContext);

return (
<div>
<h1>User: {username}</h1>
</div>
)
}

export default User;

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))

Séance 11 : Consommation des API


(fetch() & Axios API)

 Voir document pdf

94 / 158
Séance 13 : React Rooter

Step 1: Create React Project

npm create-react-app myreactapp

Step 2: Change your directory and enter your main folder charting as :

cd myreactapp

Step 3: To install react-router in your application write the following


command in your terminal:

npm install react-router-dom


Or
npm i react-router-dom

Step 4: Importing React Router:

import { BrowserRouter, Routes, Route } from "react-router-dom";

 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>
);
}

export default App;

Home.js
const Home = () => {
return (
<div>
<h2>Home</h2>
</div>
);
};

export default Home;

About.js
const About = () => {
return (
<div>
<h2>About</h2>
</div>
);
};

export default About;

96 / 158
Contact.js
const Contact = () => {
return <h2>Contact Me</h2>;
};

export default Contact;

NoPage.js
const NoPage = () => {
return <h1>404</h1>;
};

export default NoPage;

Liens : 1 - https://www.geeksforgeeks.org/reactjs-router/
2 - https://velopert.com/3417

 Menu avec Posts : (https://velopert.com/3417)

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 Posts from './pages/Posts';
import NoPage from './pages/NoPage';

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>
);
}

export default App;


Post.js
const Post = ({match}) => {
return (
<div>
Post {match.params.id}
</div>
);
};

export default Post;


Posts.js
import { Link, Route } from 'react-router-dom';
import Post from './Post';

const Posts = ({match}) => {


return (
98 / 158
<div>
<h2>Post List</h2>
<ul>
<li><Link to={`${match.url}/1`}>Post
#1</Link></li>
<li><Link to={`${match.url}/2`}>Post
#2</Link></li>
<li><Link to={`${match.url}/3`}>Post
#3</Link></li>
<li><Link to={`${match.url}/4`}>Post
#4</Link></li>
</ul>
<Route exact path={match.url}
render={()=>(<h3>Please select any post</h3>)}/>
<Route path={`${match.url}/:id`} component={Post}/>
</div>
);
};

export default Posts;

Séance 16
Concevoir une application avec Redux

Step 1: Change your directory and enter your main :

cd myreactapp

Step 2: To install react-redux in your application write the following


command in your terminal:

npm install react-redux

Qu’est-ce que le store ?

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>
)

export default Article;


components/AddArticle.jsx
import React, { useState } from "react"

const AddArticle = ({ saveArticle }) => {


const [article, setArticle] = useState()

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>
)
}

102 / 158
export default AddArticle;

components/Articles.jsx
import React, { useState } from "react"
import Article from "../components/Article"
import AddArticle from "../components/AddArticle"

const Articles = () => {


const [articles, setArticles] = useState([
{ id: 1, title: "post 1", body: "Quisque cursus, metus
vitae pharetra" },
{ id: 2, title: "post 2", body: "Quisque cursus, metus
vitae pharetra" },
])

const saveArticle = article => {


setArticles([...articles, article])
}

return (
<div>
<AddArticle saveArticle={saveArticle} />
{articles.map(article => (
<Article key={article.id} article={article} />
))}
</div>
)
}

export default Articles;


App.js
import Articles from "./components/Articles";

function App() {

return (
<div>
<Articles />
</div>

103 / 158
)

export default App;

 Exemple : Avec Redux

components/Article.jsx
const Article = ({ article }) => (
<div className="article">
<h1>{article.title}</h1>
<p>{article.body}</p>
</div>
)

export default Article;


components/AddArticle.jsx
import React, { useState } from "react"

const AddArticle = ({ saveArticle }) => {


const [article, setArticle] = useState()

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>
)
}

export default AddArticle;

Comment dispatcher une action au store Redux depuis un composant


React ?
components/Articles.jsx
import React, { useState } from "react"
import { connect } from "react-redux"
import Article from "../components/Article"

105 / 158
import AddArticle from "../components/AddArticle"
import { addArticle } from "../store/actionCreators"

const Articles = ({articles, saveArticle}) => (


<div>
<AddArticle saveArticle={saveArticle} />
{articles.map(article => (
<Article key={article.id} article={article} />
))}
</div>
)

const mapStateToProps = state => {


return {
articles: state.articles,
}
}

const mapDispatchToProps = dispatch => {


return {
saveArticle: article =>
dispatch(addArticle(article)),
}
}

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>
)
}

export default App;


store/reducer.js
import * as actionTypes from "../store/actionTypes"

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
}

export default reducer;

store/actionCreators.js
import * as actionTypes from "../store/actionTypes"

export const addArticle = article => {


return {
type: actionTypes.ADD_ARTICLE,
article,

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 }) => {

const supprimerArt = e => {


removeArt(article.id)
}

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"

const AddArticle = ({ saveArticle }) => {


const [article, setArticle] = useState()

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>

109 / 158
</form>
)
}

export default AddArticle;

components/Articles.jsx
import { connect } from "react-redux"
import Article from "../components/Article"
import AddArticle from "../components/AddArticle"
import { addArticle,removeArticle } from
"../store/actionCreators"

const Articles = ({articles, saveArticle, removeArt}) => (


<div>
<AddArticle saveArticle={saveArticle} />
{articles.map(article => (
<Article key={article.id} article={article}
removeArt={removeArt} />
))}
</div>
)

const mapStateToProps = state => {


return {
articles: state.articles,
}
}

const mapDispatchToProps = dispatch => {


return {
saveArticle: article =>
dispatch(addArticle(article)),
removeArt: index =>
dispatch(removeArticle(index))
}
}

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>
)
}

export default App;


store/reducer.js
import * as actionTypes from "./actionTypes"

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),
}

111 / 158
case actionTypes.REMOVE_ARTICLE:
return {
state,
articles: state.articles.filter((art) =>
art.id!==action.indice),
}
}
return state
}

export default reducer;

store/actionCreators.js
import * as actionTypes from "./actionTypes"

export const addArticle = article => {


return {
type: actionTypes.ADD_ARTICLE,
article,
}
}

export const removeArticle = index => {


return {
type: actionTypes.REMOVE_ARTICLE,
indice: index
}
}
store/actionTypes.js
export const ADD_ARTICLE = "ADD_ARTICLE" ;
export const REMOVE_ARTICLE = "REMOVE_ARTICLE" ;
export const FIND_ARTICLE = "FIND_ARTICLE" ;

 Exemple 2 : Compteur.

112 / 158
store/reducer.js
const initialState = {num:0}

const reducer = (state = initialState, action) => {


switch (action.type) {
case "Incrementer" :
return { ...state, num : state.num + 1}
case "Decrementer" :
return { ...state, num : state.num - 1}
case "Reset" :
return { ...state, num : 0}
default :
return state
}
}

export default reducer;

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() {

const store = legacy_createStore(reducer)

return (
<Provider store={store}>
<Compteur />
</Provider>
);
}

export default App;


components/Compteur.js
import { useDispatch, useSelector} from "react-redux"

const Compteur = () => {


const num = useSelector(data => data.num)
const dispatch = useDispatch()

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>
)
}

export default Compteur;


index.css
p {
font-size: 24px;
font-weight: bold;
margin-left: 120px;
}
114 / 158
button {
margin: 1px;
font-weight: bold;
}

 Exemple 3 : Gestion d’un panier.

3 composants : ListFruits, Fruiterie et App

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'

export function addFruit(myFruit){


return({
type:type.ADD_FRUIT,
fruit:myFruit
})
}

export function viderFruit(){


return({
type:type.REMOVE_ALL_FRUITS
})
}
reducerFruits.js
import * as type from '../store/typeActions'

const initialeState={ fruits:[] }

export default function reducerFruits(state=initialeState,action){


switch(action.type){
case type.ADD_FRUIT:
return {...state,fruits:[...state.fruits,action.fruit]}
case type.REMOVE_ALL_FRUITS:
return {...state,fruits:[]}
default:
return state
}
}

116 / 158
ListFruits.js
import {connect} from 'react-redux'
import { addFruit, viderFruit } from '../store/actionsFruit'

function ListFruits(props){

return (<div className='fruits'>


<h5>Composant liste fruits</h5>
<ul>
{props.fruits.map((fruit,index) =>
<li key={index}>{fruit}</li>)}
</ul>
</div>)
}

function mapStateToProps(state){
return {fruits:state.fruits}
}

export default connect(mapStateToProps,null)(ListFruits)


Fruiterie.js
import {useState} from 'react'
import { connect} from 'react-redux'
import {addFruit,viderFruit} from '../store/actionsFruit'
import ListFruits from './ListFruits'

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())}
}
}

export default connect(null,mapDispatchToProps)(Fruiterie)


App.js
import { Provider } from "react-redux"
import { legacy_createStore } from "redux"
import reducer from "./store/reducerFruit";
import Fruiterie from "./components/Fruiterie";

function App() {

const store = legacy_createStore(reducer)

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)
}

 Suppresion d’un fruit :

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
})
}

export function removeFruit(index){


return({
type:type.REMOVE_FRUIT,
indice:index
})
}

export function viderFruit(){


return({
type:type.REMOVE_ALL_FRUITS
})
}

reducerFruits.js
import * as type from '../store/typeActions'

const initialeState={
fruits:[]
}

export default function reducerFruits(state=initialeState,action){


switch(action.type){
case type.ADD_FRUIT:
return {...state,fruits:[...state.fruits,action.fruit]}
case type.REMOVE_FRUIT:
return {...state, fruits:state.fruits.filter(f =>
state.fruits.indexOf(f)!==action.indice)}
case type.REMOVE_ALL_FRUITS:
return {...state,fruits:[]}
default:
return state
}
}
120 / 158
ListFruits.js
import {connect} from 'react-redux'
import { removeFruit } from '../store/actionsFruit'

function ListFruits(props){

return (<div className='fruits'>


<h5>Composant liste fruits</h5>
<ul>
{props.fruits.map((fruit,index)=><li
key={index}>{fruit}
<button onClick={() =>
props.supprimerFruit(index)}>X</button></li>)}
</ul>
</div>)
}

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)

 Utilisation de : useSelector () et useDispatch()


 useSelector()
Permet d’extraire des données du store de Redux (state) à utiliser dans ce
composant.
Le sélecteur est approximativement équivalent à l'argument mapStateToProps
pour se connecter conceptuellement.
 useDispatch()
Permet de dispatcher une action au store Redux depuis un composant React.

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'

export function addFruit(myFruit){


return({
type:type.ADD_FRUIT,
fruit:myFruit
})
}

export function viderFruit(){


return({
type:type.REMOVE_ALL_FRUITS
})
}
reducerFruits.js
import * as type from '../store/typeActions'

const initialeState={
fruits:[]
}

export default function reducerFruits(state=initialeState,action){


switch(action.type){
case type.ADD_FRUIT:
return {...state,fruits:[...state.fruits,action.fruit]}
case type.REMOVE_FRUIT:
return {...state, fruits:state.fruits.filter(f =>
state.fruits.indexOf(f)!==action.indice)}
case type.FIND_FRUIT:
return {...state, fruits:state.fruits.filter(f =>
state.fruits.indexOf(f)===action.indice)}
case type.REMOVE_ALL_FRUITS:
return {...state,fruits:[]}
default:
return state

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()

return (<div className='fruits'>


<h5>Composant liste fruits</h5>
<ul>
{fruits.map((fruit,index)=><li key={index}>{fruit}
<button onClick={() =>
dispatch(removeFruit(index))}>X</button>
</li>)}
</ul>
</div>)
}

export default ListFruits;


Fruiterie.js
import {useState} from 'react'
import { useDispatch} from 'react-redux'
import {addFruit,viderFruit} from '../store/actionsFruit'
import ListFruits from './ListFruits'

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>)
}

export default Fruiterie;


App.js
import { Provider } from "react-redux"
import { legacy_createStore } from "redux"
import reducer from "./store/reducerFruit";
import Fruiterie from "./components/Fruiterie";

function App() {

const store = legacy_createStore(reducer)

return (
<Provider store={store}>
<Fruiterie />
</Provider>
);
}

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;
125 / 158
padding: 8px;
width: 260px;
max-width: 160px;
background-color: rgb(221, 208, 247);
border:1px solid rgb(14, 19, 33)
}

Synthèse : CRUD avec React

 Installer JSON Server :

npx json-server --watch data/db.json --port 8000

Port 8000 parceque le port 3000 est utilise par le serveur react.

126 / 158
Add :

Edit & Delete :

axios.get('http://localhost:8000/fruits').then((res) =>
setFruits(res.data))

axios.post('http://localhost:8000/fruits', {id: id,name:


name,price: price})

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))
})

const handleSubmit = (event) => {


event.preventDefault();
const id = fruits[fruits.length - 1].id +1;
axios.post('http://localhost:8000/fruits', {id: id,name:
name,price: price})
}

const handleEdit = (id) => {


axios.get('http://localhost:8000/fruits/'+id).then((res)
=> {
setUname(res.data.name)
setUprice(res.data.price)
})
setEditID(id)
}

const handleUpdate = () => {


axios.put('http://localhost:8000/fruits/'+editID, {id:
editID,name: uname,price: uprice})
.then(() => {setEditID(-1)})
}

const handleDelete = (id) => {


axios.delete('http://localhost:8000/fruits/'+id)
}

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>
)
}

export default Table;

App.js
import Table from "./Table";

function App() {
return (
<div>
<Table />
</div>
);
}

export default App;

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()

const handleSubmit = (event) => {


event.preventDefault()
const id = props.fruits[props.fruits.length - 1].id +1;
axios.post('http://localhost:3000/fruits',{id:id,
name:name, price:price});
}

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>
)
}

export default AddFruit;

ListHeader.jsx
function ListHeader () {

return (
<>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Action</th>
</>
)
}

export default ListHeader;

LigneFruit.jsx
function LigneFruit (props) {

const handleEdit = (id) => {


props.setEditId(id)
}

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>
)
}

export default LigneFruit;

EditFruit.jsx
import axios, { axios } from 'axios'
import { useState} from 'react'

function EditFruit (props) {


const [uname, setUname] = useState()
const [uprice, setUprice] = useState()

const handleUpdate = (id)=> {


axios.put('http://localhost:3000/fruits/' + id, {id:id,
name:uname, price:uprice})
props.setEditId(-1)
}

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>
)
}

export default EditFruit;

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))
})

const handleDelete = (id) => {


axios.delete('http://localhost:3000/fruits/' + id)
}

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>
)
}

export default Table;

App.js
import Table from "./Table";

function App() {
return (
<div>
<Table />
135 / 158
</div>
);
}

export default App;

Synthèse : CRUD avec Redux


Add :

Edit & Delete :

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
})
}

export function updateFruit(unFruit){


return({
type:type.UPDATE_FRUIT,
fruit:unFruit
})
}

export function removeFruit(id){


return({
type:type.REMOVE_FRUIT,
id:id
})
}

export function findFruit(index){


return({
type:type.FIND_FRUIT,
indice:index
})
}

export function viderFruit(){


return({
type:type.REMOVE_ALL_FRUITS
})
}

import * as type from './typeActions'

const initialeState={
fruits:[
{
137 / 158
"id": "1",
"name": "Orange",
"price": 10
},
{
"id": "2",
"name": "Apple",
"price": 12
}
]
}

export default function


reducerFruits(state=initialeState,action){
switch(action.type){
case type.ADD_FRUIT:
return
{...state,fruits:[...state.fruits,action.fruit]}
case type.REMOVE_FRUIT:
return {...state, fruits:state.fruits.filter(f
=>
f.id!==action.id)}
default:
return state
}
}

import { useState } from "react"


import { useSelector, useDispatch } from "react-redux";
import { addFruit } from '../store/actionsFruit'

let id = 2

function AddFruit() {
const [name, setName] = useState()
const [price, setPrice] = useState()

const fruits = useSelector(data => data.fruits)


const dispatch = useDispatch()

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>
)
}

export default AddFruit;

import { useSelector,useDispatch } from "react-redux";


import { useState } from "react";
import { removeFruit } from "../store/actionsFruit";

function ListFruit () {
const fruits = useSelector(data => data.fruits)
const dispatch = useDispatch()

const handleDelete = (id) => {


dispatch(removeFruit(id))
}

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>
)
}

export default ListFruit;

import AddFruit from "./AddFruit";


import ListFruit from "./ListFruit";

function Fruiterie () {

return (
<div className='container'>
<AddFruit />
<ListFruit />
</div>
)
}
140 / 158
export default Fruiterie;

import { Provider } from "react-redux";


import {legacy_createStore} from "redux"
import reducer from './store/reducerFruits'
import Fruiterie from "./components/Fruiterie";

function App() {

const store = legacy_createStore(reducer)


return (
<Provider store={store}>
<Fruiterie />
</Provider>
);
}

export default 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

npm install @reduxjs/toolkit react-redux

Synthèse : Gestion Groupe 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"},

]
}

const GroupeSlice = createSlice({


name:"groupe",
initialState:initState,
reducers:{
addGroupe: (state, action)=>{

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;})
},

},
})

export const {deleteGroupe,addGroupe,UpdateGroupe} =


GroupeSlice.actions;
export default GroupeSlice.reducer;

Store.js
import { configureStore } from "@reduxjs/toolkit";
import GroupeSlice from "./GroupeSlice";

const store=configureStore({
reducer:{
Groupe:GroupeSlice,
},
})

export default store ;

import { useState } from 'react';


import { useDispatch, useSelector } from "react-redux";
import { deleteGroupe,addGroupe ,UpdateGroupe} from
"./GroupeSlice";

function Groupe(){
const [grId, setGrId] =useState();
const [nomg, setnomg] = useState();
let listGroupe = useSelector(state =>
state.Groupe.dbGroupes);

144 / 158
let dispatch = useDispatch();

const handleDelete = (pos) =>{


window.confirm('vous êtes sûr de supprimer ?')
&& dispatch(deleteGroupe(pos))
}

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)} />

<button className="btn btn-success" onClick={()=>{


dispatch(addGroupe({id:grId,nom :nomg}));
setGrId('');setnomg('');}}>Ajouter</button>
<button className="btn btn-danger"
onClick={()=>{dispatch(UpdateGroupe({id:grId,nom :nomg}));
setGrId('');setnomg('');}} >Modifier</button>
<h3>Liste des Voitures</h3>

<table width="60%" className=" container table


table-striped">
<thead>
<tr><th>Id Groupe</th><th>Nom
Groupe</th><th>Opération</th></tr>
</thead>
<tbody>
{
listGroupe.map((grp,index) =>
<tr key={index}>
<th>{grp.id}</th>
<th>{grp.nom}</th>
<th>
<button className="btn btn-
danger" onClick={()=>handleDelete(index)} >delete</button>
</th>
</tr>
)
145 / 158
}
</tbody>
</table></center>
</div>
);
}

export default Groupe;

App.js
import React from 'react';
import './index.css';

import { Provider } from 'react-redux';


import store from './store';
import Groupe from './Groupe';

function App() {
return (
<Provider store={store}>
<Groupe/>
</Provider>
);
}

export default App;

npx create-react-app react_crud

146 / 158
cd react_crud

npm start

npm install react-router-dom axios bootstrap json-server

npm install react-router-dom

npm install --save axios

npm install -g json-server

npx json-server --watch data/db.json –port 8000

147 / 158
https://www.geeksforgeeks.org/how-to-do-crud-operations-in-reactjs/

How to do CRUD operations in ReactJS ?

148 / 158
// Filename - App.js

import React from "react";


import {
BrowserRouter as Router,
Route,
149 / 158
Routes,
} from "react-router-dom";
import "./App.css";
import Create from "./components/Create";
import Edit from "./components/Edit";
import Home from "./components/Home";

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>
);
}

export default App;

// Filename - components/array.js

// Javascript object named array


// with 3 key-values
const array = [
{
id: "1",
Name: "Shivansh",
Age: "23",
},
{
id: "2",
Name: "Simran",
Age: "22",
},
{
id: "3",
Name: "Aakash",
Age: "23",
},
];

export default array;

// 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("");

// Using useNavigation for redirecting to pages


let history = useNavigate();

// Function for creating a post/entry


const handelSubmit = (e) => {
e.preventDefault(); // Prevent reload

const ids = uuid(); // Creating unique id


let uni = ids.slice(0, 8); // Slicing unique id

// Fetching a value from usestate and


// pushing to javascript object
let a = name,
b = age;
if (name == "" || age == "") {
alert("invalid input");
return;
}
array.push({ id: uni, Name: a, Age: b });

// Redirecting to home page after creation done


history("/");
};

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>

{/* Fetching a value from input textfirld in


a setage using usestate*/}
<Form.Group
className="mb-3"

151 / 158
controlId="formBasicAge"
>
<Form.Control
onChange={(e) =>
setage(e.target.value)
}
type="number"
placeholder="Age"
required
/>
</Form.Group>

{/* handing a onclick event in button for


firing a function */}
<Button
onClick={(e) => handelSubmit(e)}
variant="primary"
type="submit"
>
Submit
</Button>

{/* Redirecting back to home page */}


<Link className="d-grid gap-2" to="/">
<Button variant="info" size="lg">
Home
</Button>
</Link>
</Form>
</div>
);
}

export default Create;

// Filename - components/Home.js

import React from "react";


import { Button, Table } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
import array from "./array";
import { Link, useNavigate } from "react-router-dom";

function Home() {
let history = useNavigate();

// You may skip this part if you're


// using react-context api or redux
function setID(id, name, age) {
localStorage.setItem("id", id);
localStorage.setItem("Name", name);
localStorage.setItem("Age", age);
}

// Deleted function - functionality


// for deleting the entry
function deleted(id) {
let index = array
.map(function (e) {
return e.id;
})

152 / 158
.indexOf(id);

// deleting the entry with index


array.splice(index, 1);

// We need to re-render the page for getting


// the results so redirect to same page.
history("/");
}

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>

{/* getting theid,name, and


age for storing these
value in the jsx with
onclick event */}
<td>
<Link to={`/edit`}>
<Button
onClick={(e) =>
setID(
item.id,
item.Name,
item.Age
)
}
variant="info"
>
Update
</Button>
</Link>
</td>

{/* Using thr deleted function passing


the id of an entry */}
<td>
<Button
onClick={(e) =>
deleted(item.id)
}
variant="danger"
>
Delete
</Button>
</td>
</tr>
);

153 / 158
})}
</tbody>
</Table>

{/* Button for redirecting to create page for


insertion of values */}
<Link className="d-grid gap-2" to="/create">
<Button variant="warning" size="lg">
Create
</Button>
</Link>
</div>
);
}

export default Home;

// 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("");

// Used for navigation with logic in javascript


let history = useNavigate();

// Getting an index of an entry with an id


let index = array
.map(function (e) {
return e.id;
})
.indexOf(id);

// Function for handling the edit and


// pushing changes of editing/updating
const handelSubmit = (e) => {
// Preventing from reload
e.preventDefault();
if (name == "" || age == "") {
alert("invalid input");
return;
}

// Getting an index of an array


let a = array[index];

// Putting the value from the input


// textfield and replacing it from
// existing for updation
a.Name = name;

154 / 158
a.Age = age;

// Redirecting to main page


history("/");
};

// Useeffect take care that page will


// be rendered only once
useEffect(() => {
setname(localStorage.getItem("Name"));
setage(localStorage.getItem("Age"));
setid(localStorage.getItem("id"));
}, []);

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>

{/* setting a age from the input textfiled */}


<Form.Group
className="mb-3"
controlId="formBasicPassword"
>
<Form.Control
value={age}
onChange={(e) =>
setage(e.target.value)
}
type="number"
placeholder="Age"
/>
</Form.Group>

{/* Hadinling an onclick event


running an edit logic */}
<Button
onClick={(e) => handelSubmit(e)}
variant="primary"
type="submit"
size="lg"
>
Update
</Button>

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>
);
}

export default Edit;

/* App.css */
.App {
text-align: center;
}
.geeks {
color: green;
}

npm i json-server

json-server --watch db.json

156 / 158
**** Commandes Json-server :

npm install json-server  istallation locale

npm install -g json-server  istallation globale

npm install json-server@latest

npm ls json-server  afficher version

json-server --watch db.json

npx json-server --watch data/db.json --port 8000

Liens:
https://react.dev/learn/updating-arrays-in-state

157 / 158
158 / 158

You might also like