Vous êtes sur la page 1sur 49

1.

cours React
ISEN 2021
Thomas  Fritsch
1.2

thomas@uidlt.fr

Dev front & consultant Formateur & enseignant

JS / React / React Native / Node.js


PROGRAMME
1.4

1. Rappels
2. Syntaxes ES6+
3. Premiers pas avec React
4. Les composants
5. Formulaires et AJAX
6. Hooks & React Router
7. Redux
2.1

JAVASCRIPT,
POURQUOI
TANT
DE
HAINE ?
2.2

M. , prof de JAVA à l'Université de Lille, le 14 mars 2018

“ Franchement, JavaScript, c'est un langage

merdique  ! ”
2.3
POURQUOI ?
2.4

pas de typage fort


pas de POO
scope incompréhensible
"this" aléatoire
pas d'outils de dev sérieux
variables globales par défaut
pas de gestion des dépendances
ne marche pas dans tous les navigateurs
une sous-version pourrie de JAVA
2.5

ON VOUS
MENT !
tout ça c'est du passé
1. UNIVERSEL
2.6

99% des terminaux compatibles

2. MULTI SUPPORT
browser / serveur / desktop / mobile / IOT

3. STANDARD DE
L'INDUSTRIE...
2.7


SUR LES 5 PREMIERS
PROJETS GITHUB
3 UTILISENT JS

Notes :

Source : https://github.com/search?o=desc&q=stars%3A%3E59500&s=stars&type=Repositories

NB: n'est pas compté dans le classement le repo 996.ICU dénonçant les conditions de travail dans certaines
entreprises chinoises et qui n'est pas un projet de dev.
LANGAGES LES + DEMANDÉS
2.8

Offres d'emploi sur Indeed France - Jan. 2021


8 172
7 923

Notes :

Statistiques d'offres d'emploi en france sur indeed (janvier 2021) :

langage source nb
emplois
javascript OR js OR https://fr.indeed.com/emplois? 8 172
typescript q=%22javascript%22+OR+%22js%22+OR+%22typescript%22&l=
java https://fr.indeed.com/emplois?q=%22java%22&l= 7 923
python https://www.indeed.fr/emplois?q=python&l= 7 468
PHP https://fr.indeed.com/emplois?q=%22PHP%22&l= 4 428
c++ https://fr.indeed.com/emplois?q=%22c%2B%2B%22&l= 3 326
c# https://www.indeed.fr/emplois?q=c%23&l= 3 361
Perl https://www.indeed.fr/emplois?q=Perl&l= 1 401
Scala https://www.indeed.fr/emplois?q=scala&l= 701
Swi https://www.indeed.fr/emplois?q=swi &l= 660
Ruby https://www.indeed.fr/emplois?q=Ruby&l= 535
Cobol https://fr.indeed.com/emplois?q=%22cobol%22&l= 429
Objective C https://www.indeed.fr/emplois?q=Objective+C&l= 426
2.9

Notes :

Spotify utilise JS pour le développement de son application Desktop

Source : https://www.quora.com/How-is-JavaScript-used-within-the-Spotify-desktop-application-Is-it-
packaged-up-and-run-locally-only-retrieving-the-assets-as-and-when-needed-What-JavaScript-VM-is-
used/answer/Mattias-Petter-Johansson

"The Spotify desktop client UI is completely built with JavaScript, resting on top
of the same C++ core that the iOS and Android clients uses."
2 . 10

Notes :

https://www.skype.com/fr/features/

Les applis Skype desktop et mobile sont codées en JS

Sources : https://electronjs.org/apps/skype & https://facebook.github.io/react-native/showcase.html


2 . 11

Notes :

Le client desktop de Discord ainsi que l'appli mobile sont aussi développés avec JavaScript (Electron)

Source : https://en.wikipedia.org/wiki/Discord_(so ware)#cite_ref-15 & https://facebook.github.io/react-


native/showcase.html
2 . 12

Notes :

Uber utilise JavaScript côté serveur avec Node.JS

Source : https://foundation.nodejs.org/wp-content/uploads/sites/50/2017/09/Nodejs-at-Uber.pdf
2 . 13

Notes :

Les applis serveur de Netflix utilisent aussi Node.JS

Source : https://medium.com/netflix-techblog/node-js-in-flames-ddd073803aa4
mais alors...
2 . 14

CES GENS LÀ AIMENT-ILS


LE CODE SALE ?
ECMASCRIPT ?
2 . 15

la Spec suivie par JavaScript


beaucoup ne connaissent qu'ES5 (2009)
ES6 sorti en 2015 ! nouvelle syntaxe, nouvelles possibilités
depuis, une nouvelle version / an : ES7, ES8, ES9, ES10...
POO, gestion des dépendances, block scope,
Promises/Futures, ...
3.1

React
1. Rappels
2. Syntaxes ES6+
3. Premiers pas avec React
4. Les composants
5. Formulaires et AJAX
6. Hooks & React Router
7. Redux
3.2

1. RAPPELS
client/serveur & SPA

HTML JS
CLIENT / SERVEUR
3.4

CLIENT (NAVIGATEUR) SERVEUR HTTP

www.amc.com/breaking-bad   GET  /breaking-bad  HTTP/1.1 (Request)

HTML

  HTTP/1.1  200  OK (Response)
+ headers
+ body

Notes :

“ L'environnement client-serveur désigne un mode de communication à travers


un réseau entre plusieurs programmes ou logiciels :
l'un, qualifié de client, envoie des requêtes ;
l'autre ou les autres, qualifiés de serveurs, attendent les requêtes des clients et
y répondent.

Wikipedia

Sous windows,on peut utiliser le programme telnet pour lancer des requêtes http. Dans un terminal /
command prompt, taper : telnet www.amc.com 80 puis :

GET /shows/breaking-bad--18 HTTP/1.1


Host: www.amc.com

Terminer par un double retour à la ligne à la fin qui indique au serveur la fin de la requête. Le serveur retourne
une Réponse "301 Moved permanently" car le http est automatiquement redirigé vers le https.

Pour effectuer des requêtes https, il faut utiliser openssl : openssl s_client -connect
www.amc.com:443 puis taper comme précédemment:

GET /shows/breaking-bad--18 HTTP/1.1


Host: www.amc.com
NAVIGATION
3.5

CLIENT (NAVIGATEUR) SERVEUR HTTP

www.amc.com/breaking-bad/episodes   GET  /breaking-bad/episodes HTTP/1.1 (R

HTML

  HTTP/1.1  200  OK (Response)
+ headers
+ body

Notes :

Dans un scénario de navigation classique, lorsque l'on clique sur un lien hypertexte, le navigateur envoie une
nouvelle requête HTTP vers la nouvelle URL, et remplace le contenu affiché dans la fenêtre par celui retourné
par le serveur.

Tout est remplacé, même si seulement certaines parties de la page ont été modifiées.

Le problème principal de ce mode de navigation se situe au niveau des performances et de l'expérience


utilisateur : à chaque clic sur un lien on a un rechargement complet de la page.
SINGLE PAGE APP
3.6

Une seule page HTML + navigation en JS

CLIENT (NAVIGATEUR) SERVEUR HTTP

www.amc.com/breaking-bad/episodes

  GET  /api/episodes  HTTP/1.1(Request)

JSON (données brutes)


  HTTP/1.1  200  OK (Response)
chargement en cours...
+ headers + body

Notes :

Dans une "Single Page App" on a une seule page HTML dont le rendu va être piloté en JS :

1. l'utilisateur clique sur un lien de la page


2. le JS intercepte le clic et lance en arrière plan une requête HTTP vers le serveur (AJAX)
3. le serveur retourne les données au format brut (JSON/XML/...)
4. le JS parse les données reçues ...
5. ... et modifie le code HTML de la page (API DOM)

Les avantages sont multiples :

volume de données téléchargé plus faible


donc temps de chargement plus courts
et charge serveur plus faible
meilleure expérience utilisateur
3.7

1. RAPPELS
client/serveur & SPA
HTML ♥ JS
HTML + JS : INTÉGRATION
3.8

Inline
<a href="#" onclick="alert('Welcome to Albuquerque');return false;">
BB
</a>

Dans une balise script


<script>alert('Welcome to Albuquerque');</script>

Dans un fichier externe


<script src="welcome.js"></script>
HTML + JS : MAIS T'ES OÙ ?
3.9

<!doctype html>
<html>
<head>
<title>J. P. Wynne High School Presentation</title>
<meta charset="utf-8">
<script src="build/main.js" defer></script> <!-- B : --> 🏆
</head>
<body>
<p>Public high school located in Albuquerque, New Mexico. It's the
perfect place to steal methlab equipment.</p>
</body>
</html>

Notes :

Il ya plusieurs façons d'intégrer des balises script dans une page html mais depuis quelques temps déjà c'est
l'attribut "defer" que je vous recommande d'utiliser sur une balise dans le <head>.

Avec cet attribut :

le chargement du JS ne bloquera pas le parsing de la page HTML


le code qu'il contient ne sera exécuté que quand la page sera intégralement chargée

Voir : https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer

Presque toutes les versions en circulation de presque tous les navigateurs supportent cet attribut, il peut donc
être utilisé sans soucis en production : https://caniuse.com/#feat=script-defer
IMPACT SUR L'UX
3 . 10

(SKYWALKER)

<script> à la fin du body


parsing HTML
chargement JS

<script> dans le head


parsing HTML
chargement JS

<script> dans le head + defer


parsing HTML
chargement JS

Notes :

L'intégration de l'attribut defer permet de ne pas bloquer le parsing de la page html, mais en même temps de
n'exécuter son code qu'une fois que toute la page html est parsée pour éviter les bugs d'accès au contenu de
la page.

Plus de précisions sur les différentes possibilités : https://www.growingwiththeweb.com/2014/02/async-vs-


defer-attributes.html
4.1

React
1. Rappels
2. Syntaxes ES6+
3. Premiers pas avec React
4. Les composants
5. Formulaires et AJAX
6. Hooks & React Router
7. Redux
4.2

2. SYNTAXES ES6+
Les bases
POO
Modules
ES6 : LET
4.3

remplace "var"
scopée
let i = 0;
for ( let i = 1; i < tableau.length; i++ ) {
console.log( i ); // 1, 2, 3, ...
}
console.log( i ); // 0

Notes :

Fonctionne exactement comme le var traditionnellement employé. Cependant, le let a la particularité


d'être scopé au niveau du bloc de code dans lequel il est déclaré, et pas forcément dans toute la fonction.
ES6 : CONST
4.4

déclaration de constante
scopée
const hello; // Erreur : une constante doit avoir une valeur !
const hello = 'Hello';

if (true) {
const hello = 'Bonjour';
hello = 'Hola'; // Erreur : une constante ne peut être modifiée !
console.log(hello); // "Bonjour"
}

console.log(hello); // "Hello"

Notes :

const permet de déclarer une constante. De plus, comme le let, une variable const est scopée au niveau
du bloc de code et non pas de la fonction comme le var.
ES6 : CONST ?
4.5

const ingredients; // ⛔ Erreur : une constante doit avoir une valeur

const ingredients = ['methanol', 'red phosphorus']; // 👍


ingredients = ['methanol', 'red phosphorus', 'pseudo']; // ⛔
Erreur :
// réassignation impossible
ingredients.push('pseudo'); // 👍
ES6 : TEMPLATES STRINGS
4.6

Nouveau délimiteur de chaîne : `


Injection d'expressions (variable ou appel de fonction)
multiline
const value = `danger`;
let phrase = `I am the ${ value } !`; // I am the danger !

function myFunction(valeur) {
return valeur;
}
phrase = `I am the ${ myFunction('danger') } !`; // I am the danger !

function renderLink( target, cssClass, href ) {


return `<a href="${ href.toLowerCase() }"
class="${ cssClass }"
target="${ target }">
Cliquez ici !
</a>`; // multiline !
}
ES6 : DESTRUCTURING
4.7

déclarer des variables au nom d'une propriété d'objet


... ou qui correspondent aux valeurs d'un tableau
const personnage = { prenom: 'Skyler', nom: 'White' };
// const prenom = personnage.prenom, nom = personnage.nom;
const { prenom, nom } = personnage;
console.log(`Salut ${prenom} ${nom} !`);

function maFonction( {prenom, nom} ) {


return `Salut ${prenom} ${nom} !`;
}
maFonction( personnage );

const tableau = [ 'Walter Jr', 'White' ];


// const prenom = tableau[0], nom = tableau[1];
const [ prenom, nom ] = tableau;

Notes :

Le destructuring permet de faciliter la création et l'assignation de variables à partir issues d'objets ou de


tableaux.

http://codepen.io/kumquats/pen/dXWxzW?editors=0011
ES6 : ARROW FUNCTIONS
4.8

déclaration de fonction simplifiée


return implicite
scope préservé
// Fonction anonyme en ES5
var add = function( a, b ) {
return a + b;
}

// et en ES6 (opérateur "fat arrow")


const add = ( a, b ) => a + b;
const square = x => x * x;
// si un seul paramètre, pas besoin de parenthèses

Notes :

La valeur de this dans une arrow function est toujours celui dans lequel elle est déclarée :

const character1 = {
name: 'hank',
link: document.querySelector('a.link'),
init: function(){
this.link.addEventListener( 'click',
(event)=>{
event.preventDefault();
console.log(this.name);
}
);
}
}
character1.init();

cf. https://codepen.io/uidlt/pen/wvGLwmL?editors=1001
PROBLÈME : SUPPORT
4.9

NAVIGATEUR
4 . 10

Notes :

Le support navigateur est très partiel, notamment sur IE. Il faut noter que chaque feature ES6 dispose de son
propre support navigateur de manière indépendante. http://caniuse.com/#search=es6

http://kangax.github.io/compat-table/es6/ Autre tableau détaillé, navigateur par navigateur du support des


différentes fonctionnalités ES6.

Pour ES2016 et suivantes voir http://kangax.github.io/compat-table/es2016plus/ et pour les features encore en


cours de normalisation : http://kangax.github.io/compat-table/esnext/
4 . 11

Notes :

BabelJS https://babeljs.io/

Babel est un compilateur de code ES6+ en ES5.

Cet outil permet de rendre notre application JS compatible avec les vieux navigateurs.

Le principe est le suivant :

on code de manière élégante à l'aide des dernières features du langage (ES6+)


Babel compile le tout en ES5 (compatible avec les anciens navigateurs),
c'est ce fichier compilé qui sera mis en ligne et servi aux visiteurs
4 . 12

Notes :

Babel dispose d'un outil en ligne qui permet de tester la conversion de code ES6+ en ES5. Cet outil a surtout un
but pédagogique : montrer comment les syntaxes ES6+ permettent d'avoir un code plus propre et plus lisible
que son équivalent en ES5.

Outil de test en ligne du compilateur babel (repl)

babel repl pré-rempli avec des exemples de code ES6


5.1

2. SYNTAXES ES6+
Les bases
POO
Modules
LA VIELLE SYNTAXE ES5
5.2

function Character( firstName, lastName ) {


this.firstName = firstName; // propriétés
this.lastName = lastName;
}
Character.prototype.fullName = function() { // méthode
return this.firstName + ' ' + this.lastName;
}

// héritage
function Salamanca( firstName ){
Character.call(this, firstName, 'Salamanca' ); // super
}
Salamanca.prototype = new Character(); // héritage
var uncle = new Salamanca( 'Hector' );
console.log( uncle.fullName() );

Notes :

Exemple : https://codepen.io/uidlt/pen/gOrJVRx?editors=0011
POO ES6+ : CLASS
5.5

class Character {
firstName = 'unknown'; // propriété publique "firstName" (ES2021 ?)
lastName; // undefined

constructor(firstName, lastName) { // constructeur de la classe


this.firstName = firstName; // on écrase la valeur initiale
this.lastName = lastName;
}
fullName(){ // déclaration de méthode
return `${this.firstName} ${this.lastName}`;
}
}
const heisenberg = new Character('Walter', 'White');
console.log( heisenberg.firstName ); // accès à la propriété
console.log( heisenberg.fullName() ); // appel de la méthode

Notes :

https://codepen.io/uidlt/pen/mdPZdbg?editors=0011

Avec la nouvelle syntaxe ES6, il est désormais possible de déclarer une classe à l'aide du mot clé class. Tout ce
qui est contenu dans une classe est exécuté en mode strict.

La méthode constructor permet d'initialiser de nouvelles instances. Il ne peut y avoir qu'un seul constructeur
par classe et il est facultatif.

La création de propriétés d'instance se fait habituellement dans le constructeur à l'aide du mot clé this.

On peut aussi déclarer des propriétés en dehors du constructeur comme montré dans l'exemple ci-dessus
mais il s'agit d'une syntaxe qui n'est pas encore dans la spec officielle : cette syntaxe est en stage 3 de
spécification c'est à dire l'avant dernier niveau avant l'intégration dans la spec officielle.

On ne sait pas encore si cette syntaxe a des chances d'être intégrée ou pas dans la version ES12/ES2021 de la
spec

cf. https://github.com/tc39/proposal-class-fields et https://tc39.github.io/proposal-class-fields/


POO ES6+ : HÉRITAGE
5.6

class Salamanca extends Character {


isDead = false; // propriété supplémentaire
constructor( firstName ){
super( firstName, 'Salamanca' ); // constructeur parent
if ( this.firstName === 'Tuco' ) {
this.isDead = true;
}
}
fullName() { // override de la méthode fullName()
const result = super.fullName(); // appel de la méthode parente
return result.toUpperCase();
}
}
const uncle = new Salamanca('Hector');
console.log( uncle.fullName() ); // hérite des méthodes de Character

Notes :

Grâce au mot clé extends, l'héritage se construit de manière plus lisible qu'avec les prototypes.

Dans le constructeur de la classe fille, la méthode super() permet d'appeler le constructeur de la classe
parente. super() doit obligatoirement être appelée avant d'utiliser le mot clé "this".

super peut également servir à appeler une méthode parente (super.fullName() dans notre exemple)
6.1

2. SYNTAXES ES6+
Les bases
POO
Modules
MODULES : PROBLÉMATIQUE
6.2

<!-- Sans utilisation des modules -->


<script src="header.js"></script>
<script src="menu.js"></script>
<script src="breadcrumb.js"></script>
<script src="footer.js"></script>
<script src="main.js"></script>

<!-- Avec utilisation des modules -->


<script type="module" src="main.js"></script>

Notes :

Le système de modules permet de gérer plus facilement les dépendances entre les différents fichiers de notre
application.

Au lieu de lister à plat l'ensemble des fichiers requis par notre application (dans l'ordre adéquat !) c'est le
fichier JS principal qui indique les fichiers dont il dépend, qui eux même indiquent les fichiers dont ils
dépendent et ainsi de suite.

Ce mécanisme est particulièrement utile lorsque l'on développe des applications utilisant de nombreux
fichiers et notamment des librairies tierces.
MODULES : PRINCIPE
6.3

 vehicle.js
const vehicle = 'the RV';
export default vehicle;

 main.js
import vehicle from './vehicle.js';
console.log( vehicle ); // 'The RV'

Notes :

Le principe des modules est de diviser le code JavaScript en plusieurs fichiers appelés "modules".

Toutes les variables contenues dans un module ne sont par défaut disponibles qu'au sein de ce module. En
revanche il est possible d'exporter certaines variables afin de les exposer au reste de l'application.

Un module peut ainsi récupérer les valeurs exportées depuis un autre module grace à l'instruction "import".
MODULES : EXPORTS MULTIPLES
6.4

 vehicle.js
const vehicle = 'the RV';
const owner = 'Jesse Pinkman';
export default vehicle;
export const message = 'owner is ' + owner;

 main.js
import vehicle from './vehicle.js';
import { message, owner } from './vehicle.js';
console.log( message, owner ); // 'Owner is Jesse Pinkman', undefined

Notes :

Un module peut exporter plusieurs valeurs, mais une seule peut être l'export par défaut.

Pour exporter des valeurs supplémentaires, il suffit d'utiliser l'instruction export suivi de la valeur, sans le
mot clé default.

Au niveau des imports, il y a là aussi une différence : il faut entourer le nom de la (ou des) valeur qu'on veut
importer avec des accolades :

import { maValeur } from './monModule.js';

On peut tout à fait importer plusieurs valeurs avec une seule instruction import, il faut alors séparer les valeurs
par des virgules :

import { maValeur1, maValeur2 } from './monModule.js';

Si l'on veut récupérer à la fois l'export par défaut et d'autres exports avec une seule instruction alors on peut
écrire :

import maValeurParDefaut, { maValeur1, maValeur2 } from


'./monModule.js';
6.5

Notes :

Support navigateur des modules ES6 : https://caniuse.com/#feat=es6-module

Le support des modules ES6 est grandissant et tous les navigateurs modernes supportent désormais cette
syntaxe.

Mais comme bien souvent, Internet Explorer et Android browser (4.4) viennent gâcher la fête.

Heureusement est arrivé...


6.6

Notes :

https://webpack.js.org/

webpack permet de regrouper dans un seul fichier (le "bundle") l'ensemble des fichiers nécessaires au
fonctionnement de l'application et donc d'étendre le support navigateur au delà des navigateurs qui
supportent le système de modules.

Webpack permet d'intégrer différents type de "loaders".


Les loaders sont des filtres qui sont appliqués aux fichiers avant qu'ils ne soient ajoutés dans le bundle.

Le loader le plus fréquemment utilisé est babel-loader qui permet de s'assurer que les modules contenant
de l'ES6 seront bien compilés en ES5.

Vous aimerez peut-être aussi