Avoir installé nodejs et npm
NPM
Référence https://practicalprogramming.fr/npm/
Les packages que l'on peut gérer avec npm se trouvent sur le site web https://www.npmjs.com/
Les commandes de base :
// initialiser un package - il faudra ensuite répondre à des questions pour spécifier npm init -y // installer un package npm i nom_du_paquet // installer un package globalement npm i nom_du_paquet -g // installer des paquets en tant que devDependencies npm i nom_du_paquet -D
npm vs npx
Si NPM est un outil qui permet d'installer des packages, npx est un outil utilisé pour exécuter des packages.
Fonction pure
function sum(a, b) { return a + b; }
Ces fonctions sont dites « pures » parce qu’elles ne tentent pas de modifier leurs entrées et retournent toujours le même résultat pour les mêmes entrées.
En revanche, cette fonction est impure car elle modifie sa propre entrée :
function withdraw(account, amount) { account.total -= amount; }
React applique une règle stricte :
Tout composant React doit agir comme une fonction pure vis-à-vis de ses props.
Programmation impérative vs programmation déclarative
Jusqu'à maintenant nous avons programmé de manière impérative. Par exemple, si nous voulons ajouter un titre de niveau 1 dans le header de notre page html, voici à quoi le code va ressembler :
const header = document.createElement('header'); const h1= document.createElement('h1'); h1.textContent = "Titre de niveau 1"; document.body.appendChild(header); header.appendChild(h1);
L'approche impérative peut être comparée à une recette qui explique étape par étape comment créer une pizza (ici un header avec un titre sans mozzarella !).
L'approche déclarative reviendrait plutôt à commander notre pizza sans se soucier de savoir par quelle étape le pizzaiolo va devoir passer. C'est la promesse faite par React !
webpack
Webpack est le système qui va automatiquement "empaqueter" en gérant les dépendances (js,jsx, ts, css, scss, ...).
A noter, lorsque que vous utilisez create-react-app, la config de webpack se trouve dans \node_modules\react-scripts\config\webpack.config.js
JSX et les éléments React
JSX est une surcouche à javascript. Il génère du js via Babel.
Ex :
JSX |
|
---|---|
JS |
var element = React.createElement("h1", null, "Hellow world"); |
Attention
- quand on crée un élément React, on voit que le premier argument est une balise. Il faut donc choisir une et une seule balise, quitte à :
- encapsuler d’autres balises dans un unique div par exemple.
- encapsuler dans un "fragment" en utilisant <React.Fragment> </React.Fragment> ou la syntaxe raccourcie : <></>
- on remplace les attributs "class" et "for" par "className" et "htmlFor". Vous remarquerez l'emploi de la syntaxe camelCase
- les balises doivent être impérativement fermées (<img src=""> deviendra <img src="" />)
- si on veut inclure du javascript, on le fait à l'intérieur des accolades {// js ici}
Dans le cas où l'on veut utiliser un objet littéral, on utilisera donc les doubles accolades. Ex :style={{ color: props.color }}
-
il est recommandé de mettre le jsx entre parenthèses afin d’éviter les pièges d’insertion de point-virgule automatique.
-
une "balise" de component doit commencer obligatoirement par une majuscule
-
Après la compilation, les expressions JSX deviennent de simples appels de fonctions JavaScript, dont l’évaluation renvoie des objets JavaScript. Ça signifie que vous pouvez utiliser JSX à l’intérieur d’instructions if ou de boucles for, l’affecter à des variables, l’accepter en tant qu’argument, et le renvoyer depuis des fonctions
Un élément est un objet brut décrivant une instance de composant (de classe en général) ou un nœud DOM et ses propriétés souhaitées. Il contient uniquement des informations sur le type du composant (par exemple, un Button), ses propriétés (par exemple, sa color), et tous ses éléments enfants.
Un élément n’est pas une instance à proprement parler. C’est plutôt un moyen de dire à React ce que vous voulez voir à l’écran. Vous ne pouvez appeler aucune méthode sur l’élément. C’est juste un objet de description immuable avec deux champs :
- type
- props
Exercice : corriger le code jsx suivant afin qu'il ne génère plus d'erreur :
Exemple de code react représentant un élément :
Le code HTML suivant :
<button class='button button-blue'>
<b>
OK!
</b>
</button>
... sera représenté par l'élément react suivant (sous forme d’un objet brut) :
{ type: 'button', props: { className: 'button button-blue', children: { type: 'b', props: { children: 'OK!' } } } }
En savoir plus sur les éléments
Import et export
Depuis ES6, on peut gérer les dépendances entre fichiers avec les mots clés "import" et "export"
Ex
export default class Person { constructor(name) { this.name = name; } present() { console.log("hello, I'm " + this.name); } }
De cette façon, dans un autre script, on pourra avoir :
import Person from "./Person.js"; const p = new Person("Bob")
Attention, il faudra penser à appeler votre js en utilisant l'attribut type="module"
<script type="module" src="test.10-module.js">
Paramétrage de Visual Studio Code
Installer "vscode-language-babel"
Installer "Theme - Oceanic Next"
Installer “React-Native/React/Redux snippets for es6/es7”
Utiliser les raccourcis clavier suivants :
- imrc (import react component)
- ccs (create component class whitout constructor)
- cccs (create component class with constructor)
- slr (stateless component with return)
Installer "Auto import - ES6, TS, JSX, TSX"
Comme son nom l'indique, cette extension va automatiquement gérer les imports. ATTENTION à bien installer cette application car d'autres ont presque le même nom et ne fonctionnent pas aussi bien.
Installer "Prettier code formatters"
Aller dans File > Preferences > settings > Text editor > formatting et cocher “Format on save”
Activation de emmet pour les fichier javascript :
Aller dans File > preferences > settings puis cliquer sur l'icône en haut à droite pour ouvrir "settings (UI)"
Ajouter dans le fichier settings.json :
"emmet.includeLanguages": { "javascript": "javascriptreact" }
Extension chrome React Developer Tools
Cette extension permet
- de voir le hiérarchie React dans Chrome (cf onglet react dans l’inspecteur de chrome)
- de voir les propriétés states et props dans la fenêtre de droite du même onglet react
- de chercher des objects react grâce au formulaire de recherche
- de voir les propriétés d’un objet React grâce à “$r” dans la console après avoir sélectionné l’objet en question dans l’onglet “React”
Arrow function
Vous étiez habitué.e.s à une déclaration de fonction classique du type :
let maFonction = function () { //code ici }
Et bien avec React, c'est (presque) fini !!!
Voici les "arrow functions" ou "fonctions fléchées" :
let maFonction = () => { //code ici }
Dans le cas où la fonction attend un seul argument (i dans l'exemple ci-dessous), on peut même écrire :
let maFonction = i => { //code ici }
Dans le cas où la fonction retourne directement quelque chose, on peut supprimer les accolades et le return. Ex :
let auCarre = i => i * i;
Cela permet d’avoir une syntaxe plus courte que les expressions de fonction classiques.
ATTENTION : la vraie grosse différences avec les fonctions classiques réside dans la valeur de "this" (et oui encore lui -) :
Dans une "arrow function", this dépend de l'endroit où la fonction est déclarée. Par exemple, si la fonction est déclarée dans une méthode d'objet ou dans un constructeur d'objet, alors "this" sera forcément l'objet en question.
En revanche, dans une fonction classique, on sait que "this" dépend du contexte d'appel de la fonction : si la fonction est appelée depuis une instance d'objet, this devient l'instance en question.
Ex :
class Personne { constructor(nom) { this.nom = nom; this.buttonSePresenter = this.createButtonSePresenter(); } createButtonSePresenter(){ const button = document.createElement("button"); button.textContent = "Se présenter"; document.body.appendChild(button); //gestion des événements button.onclick = function() { console.log(this);//qui est this ? } return button; } sePresenter() { console.log("Bonjour, je m'appelle " + this.nom); } } const bob = new Personne("Bob");
Dans ce cas précis, quelle sera la valeur de "this" quand l'internaute cliquera sur le bouton "se présenter" ?
Reprenons cet exemple en utilisant une "arrow function" pour la gestion de l'événement click :
class Personne { constructor(nom) { this.nom = nom; this.buttonSePresenter = this.createButtonSePresenter(); } createButtonSePresenter(){ const button = document.createElement("button"); button.textContent = "Se présenter"; document.body.appendChild(button); //gestion des événements button.onclick = () => { console.log(this);//qui est this ? } return button; } sePresenter() { console.log("Bonjour, je m'appelle " + this.nom); } } const bob = new Personne("Bob");
Dans ce cas, quel sera la valeur de "this" quand l'internaute cliquera sur le bouton "se présenter" ?
Bind
La fonction bind(object) crée une nouvelle fonction qui, lorsqu'elle est appelée, a pour contexte this la valeur passée en paramètre.
ATTENTION : Cette méthode est une solution lorsque l'on veut qu'une méhode soit déclarée de façon classique (avec le mot clé function). Par exemple dans le cas de l'utilisation d'une class et que l'on veut que la méthode soit bien stockée dans le prototype du constructeur, il faut utiliser le mot clé function. Le probème récurrent concerne les méthodes gestionnaires d'événement. De façon classique (comme on l'a vu) "this" devient l'objet du dom qui est à la source de l'événement. La solution peut alors consister à "binder" cette méthode dans le constructeur avec une syntaxe du type :
this.handleEventClick = handleEventClick.bind(this);
Méthodes de tableau
map() et littéraux de gabarit
Map est une "Higher-order Functions", c'est à dire qu'elle prendre en paramètre une fonction.
Ellle crée et retourne un nouveau tableau qui transforme tous les éléments du tableau suivant la fonction anonyme (callback) que l'on donnera comme argument de call()
Ex : imaginons que l’on veuille ajouter du code html aux éléments du tableau suivant afin de visualiser une liste à puce.
const fruits = ["Banane", "Pomme", "Kiwi"]; // solution plus classique const liste_fruits = fruits.map(fruit => "<li>" + fruit + "</li>"); // solution utilisant les littéraux de gabarit const liste_fruits = fruits.map(fruit => `<li class="fruit"> ${fruit}</li>`);
indexOf()
La méthode indexOf() renvoie le premier indice pour lequel on trouve un élément donné dans un tableau. Si l'élément cherché n'est pas présent dans le tableau, la méthode renverra -1.
Ex :
let animaux = ['fourmi', 'bison', 'chameau', 'canard']; console.log(animaux.indexOf('bison'));// résultat attendu : 1
Spread operator (ou …)
L'opérateur spread permet de cloner facilement un objet :
const bob = { name: "Bob" }; const bobbis = { ... bob}; console.log(bobbis);// copie de l'objet bob attendue
L'opérateur spread permet également d'étendre un itérable (par exemple une expression de tableau ou une chaîne de caractères) en lieu et place de plusieurs arguments (pour les appels de fonctions) ou de plusieurs éléments (pour les littéraux de tableaux) ou de paires clés-valeurs (pour les littéraux d'objets).
Condition sans if via une structure de contrôle
let i = true; {i && (console.log("hello"))}
Opérateur ternaire
{i ? 'i est vrai' : 'i est faux'}
Objets et tableaux décomposés
Objet
L'object destructuring existe depuis ECMAScript 6 (2015).
La façon classique de récupérer les propriétés de l'objet p quand :
p = {nom:"Dylan", prenom:"Bob"}
const nom = p.nom; const prenom = p.prenom;
Une syntaxe plus courte existe :
const {nom, prenom} = p;
Si les noms des variables sont déjà utilisés :
const {nom:n, prenom:pr} = p;
Tableau
const fruits = ["banane", "cerise"]; const [banane,cerise] = [...fruits];
Littéraux de gabarit ou "template string"
Les littéraux de gabarits sont des littéraux de chaînes de caractères permettant d'intégrer des expressions, c'est-à-dire tout ce qui retourne une valeur.
Le caratère à utiliser s'appelle "Backticks" : ` (altGr + 7)
L'usage de base consiste à imbriquer des variables dans les chaînes, entre ${ et }. Elles se verront "remplacées" par leur valeur au moment de l'exécution.
let nb_kiwis = 3; const message = `J'ai ${nb_kiwis} kiwis dans mon panier`; // Résultat : J'ai 3 kiwis dans mon panier
Exemple avec une fonction
function timestamp() { return new Date().getTime() } const message = `Le timestamp actuel est ${timestamp()}`;