=============================== JavaScript / REACT.js / node.js =============================== .. contents:: :backlinks: top :depth: 3 :Liens_Web: * `Cours (FR) pour l'apprentissage du langage`_ : Le cours d'openclassrooms * `Doc + tuto (FR)`_ : Info sur le MDN de Mozzilla * Pour tester du code HTML, CSS et JS : `JSFiddle`_ ou `codepen.io`_ * `JavaScript Standard Style`_ : une convention de syntaxe à utiliser pour écrire du JavaScript .. _`Cours (FR) pour l'apprentissage du langage`: https://openclassrooms.com/fr/courses/1916641-dynamisez-vos-sites-web-avec-javascript .. _`Doc + tuto (FR)`: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference .. _`JSFiddle`: https://jsfiddle.net/ .. _`codepen.io`: https://codepen.io/ .. _`JavaScript Standard Style`: https://standarjs.com #### .. index:: single: JavaScript pair: WEB; JavaScript ---------- JavaScript ---------- JavaScript est un language interpréter conçu pour s'éxecuter coté client, c'est à dire directement coté navigateur. Tout comme avec le CSS, il est possible de placer le code JavaScript directement dans la page HTML ou dans un fichier séparé qui sera ensuite appeller depuis le HTML. Il était anciennement conseiller de faire l'appelle au fichier JS dans le "head" du fichier puisque c'est dans cette section que son regrouper toutes les meta-données de la page WEB. Cependant le chargement d'un fichier HTML étant séquentiel, il est conseiller de placer les scripts JS en bas de page (juste avant "") pour ne pas ralentir le chargement des autres éléments. .. code-block:: html :linenos: :force: Liste des commandes de bases ============================ Commentaires ------------ Les commentaires sont les mêmes qu'en C : .. code-block:: JavaScript :linenos: :force: // Commentaire simple /* Commentaires sur plusieurs lignes */ Interaction avec l'utilisateur ------------------------------ #. affichage d'un message à l'écran .. code-block:: JavaScript :linenos: :force: alert(); //ex: var myVar = "un message super important"; alert(myVar); #. Entrée utilisateur .. code-block:: JavaScript :linenos: :force: prompt(); //ex: var entreeClavier = prompt("tapez du texte ici : "); #. Confirmation conditionnelle .. code-block:: JavaScript :linenos: :force: confirm(); //ex: if (confirm('Voulez-vous exécuter le code JavaScript de cette page ?')) { alert('Le code a bien été exécuté !'); } /* un Popup doit s'ouvrir et demander de confirmer ([OK]) ou pas ([Annuler]) la valeur retournée est alors un booléin (true ou false) */ #. Affichage dans la console .. code-block:: JavaScript :linenos: :force: console.log("Je s'appelle Groot !"); Type ---- #. Les 3 types de bases * **number** : Ce type contient tous les types numériques ( entier et décimaux) * string * Boolean #. Connaitre le type d’une variable .. code-block:: JavaScript :linenos: :force: typeof //ex: var myVar = 2; alert(typeof myVar); #. Conversion de TYPE #. String --> Number .. code-block:: JavaScript :linenos: :force: parseInt() //ex: var myStr, myNumber; myStr = "1234"; myNumber = parseInt(myStr); #. Number --> String .. code-block:: JavaScript :linenos: :force: //ex: var myNumber, myStr; myNumber = 1234; myStr = myNumber + ''; //ex: (version simplifiée) var myVar = 12; myVar += ''; alert(typeof myVar); Opérateur --------- #. Opérateur d'égalité : "==" et "===" .. code-block:: JavaScript :linenos: :force: var a = 1; var b = 1; var c = "1"; //"==" --> contenu égale à console.log(a == b); // true console.log(a==c); // true //"===" --> contenu et type égale à console.log(a === b); // true console.log(a===c); // false #. Opérateur ternaire .. code-block:: JavaScript :linenos: :force: /* a ? [instruction 1] : [instruction 2] si a est vrai [instruction 1] sinon [instruction 2] */ // ex : var a = 1; var myVar = a ? console.log("'a' est vrai") : console.log("'a' est faux"); // "'a' est vrai" var a = 0; var myVar = a ? console.log("'a' est vrai") : console.log("'a' est faux"); // "'a' est faux" Détails syntaxiques =================== Concaténer les strings ---------------------- Il y a 2 méthodes permettant de concaténer les chaines de caractères : #. Additionner les strings .. code-block:: JavaScript :linenos: :force: var str1 = "aa" var str2 = "zz" var str12 = "STR1 : " + str1 + " STR2 : " + str2 //"STR1 : aa STR2 : zz" #. Modifier les chaines directement Pour pouvoir modifier les chaines directement, il remplacer les simples cotes < ' ... ' > ou les doubles cotes <" ... "> par des accent graves (altGR + 7) < \` ... \` > .. code-block:: JavaScript :linenos: :force: var str1 = "aa" var str_GR7 = `str1 : ${str1}` Déclaration des variables ------------------------- * Constantes Les constantes sont définies avec le préfix "const". .. code-block:: JavaScript :linenos: :force: const var_constante = "cc"; var_constante = "nn" //TypeError: invalid assignment to const `var_constante` * var "var" permet de définir une variable locale. Si la valeur de cette variable est modifiée en dehors de la portée de sa déclaration, la valeur initale sera modifiée / écrasée. .. code-block:: JavaScript :linenos: :force: var nom = "aa"; console.log("Avant le bloc : " + nom); //nom == "aa" if (true){ var nom = "zz"; console.log("Dans le bloc : " + nom); //nom == "zz" } console.log("Après le bloc : " + nom); //nom == "zz" * let "let" permet de définir une variable locale. Si la valeur de cette variable est modifiée en dehors de la portée de sa déclaration, la valeur initiale ne sera pas modifiée. .. code-block:: JavaScript :linenos: :force: let nom = "aa"; console.log("Avant le bloc : " + nom); //nom == "aa" if (true){ let nom = "zz"; console.log("Dans le bloc : " + nom); //nom == "zz" } console.log("Après le bloc : " + nom); //nom == "aa" Les objets JSON (Object) ------------------------ Les objets JSON sont l'équivalent des dictionnaires en python. On peux utiliser toute la syntaxe JSON. .. code-block:: JavaScript :linenos: :force: { id : "id1" } Extraire les clés (keys) pour les classé dans un tableau ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: JavaScript :linenos: :force: var myObject = { id1 : "id1", id2: "id2" } var keyFromObject = Object.keys( myObject ) //keyFromObject === ["id1", "id2"] Quand utiliser '[]' ou '.' pour accéder à une clef ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ On utilise '[]' dans le cas d'une itération lorsque le nom du membre n'est pas connue. A l'inverse, on utilise '.' pour un appel direct, lorsque le nom du membre est connu .. code-block:: JavaScript :linenos: :force: d={'a':1, 'b':2, 'c':3} //d --> Object { a: 1, b: 2, c: 3 } const d_str = Object.keys(d) //d_str --> Array(3) [ "a", "b", "c" ] d_str.forEach( item =>{ console.log(d[item]) } ) //1 //2 //3 d.a //1 d.b //2 d.c //3 Les fonctions ------------- #. Fonctions simples .. code-block:: JavaScript :linenos: :force: // Déclaration function myFunct(myArg1, myArg2){ // un super code ... } // appel myFunct() /* Variante */ var myFunct(myArg1, myArg2) => { //un super code ... } // Le mot clef "function" est suprimé, alors que la flèche " => " est insérée entre // les parenthèses et les accolades //si la fonction n'a pas d'argument var myFunct = () => { //un super code ... } #. Fonctions anonymes .. code-block:: JavaScript :linenos: :force: // déclaration function (myArg){ // un super code ... } #. Exécution immédiate d'une fonction, sans appel préalable .. code-block:: JavaScript :linenos: :force: (function (myArg){ // super code ... })(); /* Cette syntaxe permet d'exécuter du code isolé sans appel préalable d'une fonction. La fonction anonyme est exécutée automatiquement (et immédiatement) */ Opérateur < ... > (spread) -------------------------- L'opérateur spread ( ... ) permet d'éclater les propriétés d'un objet. Ces propriétés sont alors intégrable par d'autres objet. exemple : Création dans "personne2", d'une copie de "personne" .. code-block:: JavaScript :linenos: :force: var personne = { nom : "aa", prenom : "zz"}; var ville = "ee"; #. Sans l'opérateur spread .. code-block:: JavaScript :linenos: :force: var personne2 = { personne, ville}; personne2; {…} personne: Object { nom: "aa", prenom: "zz"} ville: "ee" #. Avec l'opérateur spread .. code-block:: JavaScript :linenos: :force: var personne2 = { ...personne, ville}; personne2; {…} nom: "aa" prenom: "zz" ville: "ee" Dans le premier cas, on constate que l'objet "personne" est maintenant une propriété de "personne2". Dans le second cas, seules les propriétés de "personne" ont été ajoutée à "personne2". Opérateur de comparaison "short-circuit" ---------------------------------------- Il existe un opérateur de comparaison qui retourne une expression seulement si la condition est vraie, contrairement à l'opérateur ternaire qui retourne une expression dans tous les cas. Cet opérateur est sous utilise le "ET" logique : && .. code-block:: JavaScript :linenos: :force: let isTrue = true let someExpression = "isTrue est vrai" isTrue && someExpression // --> "isTrue est vrai" isTrue = false isTrue && someExpression // --> flase //cette syntaxe est équivalente à : if (isTrue){ someExpression } Ça fonctionne parce qu’en JavaScript, true && expression est toujours évalué à expression, et false && expression est toujours évalué à false. La décomposition (destructuring) -------------------------------- :Liens_Web: * `Affecter par décomposistion (MDN)`_ .. _`Affecter par décomposistion (MDN)`: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Affecter_par_d%C3%A9composition **L'affectation par décomposition (destructuring en anglais)** est une expression JavaScript qui permet d'extraire (unpack en anglais) des données d'un tableau ou d'un objet grâce à une syntaxe dont la forme ressemble à la structure du tableau ou de l'objet. Ces expression peuvent être utilisée pour l'affectation de valeur à une varriable, décomposer un objet JavaScript (un Dictionnaire) ou de décomposer les propriétés d'un objet. C'est égelement la forme utilisée pour n'importer que certaines classes d'une librairie et ainsi éviter de la chargé complétement. .. code-block:: JavaScript :linenos: :force: /* Affectation */ var a, b, rest //Affectation simple [a, b] = [1, 2] //a===1, b===2 //Afectation avec un 'reste' grace à l'opérateur 'spread' [a, b, ...rest] = [1, 2, 3, 4, 5] //a===1, b===2, rest = [3, 4, 5] /* Décomposer un objet */ //Décomposition simple var o = {p: 42, q: true}; var {p, q} = o; //p===42, q===true //Décomposition sans affectation var a, b; ({a, b} = {a:1, b:2}); //Les parenthèses ( ... ) utilisées autour de l'instruction //sont nécessaires pour que la partie gauche soit bien //interprétée comme un objet littéral et non comme un bloc. //Il est également nécessaire d'avoir un point-virgule //avant les parenthèses de l'instruction car sinon, ces //parenthèses peuvent être interprétées comme un appel //de fonction. //affectation avec un nom différent var o = {p: 42, q: true}; var {p: toto, q: truc} = o; //toto===42, truc===true //Décomposer les propriétés d'objets passés en arguments var user = { id: 42, displayName: "jbiche", fullName: { firstName: "Jean", lastName: "Biche" } }; function userId({id}) { return id; } function whois({displayName: displayName, fullName: {firstName: name}}){ console.log(displayName + " est " + name); } console.log("userId: " + userId(user)); w// "userId: 42" whois(user); // "jbiche est Jean" //Cela permet d'accéder directement à id, displayName et //firstName depuis l'objet user Les classes ----------- La Création d'une classe se fait avec le mot clef : **class**. La création d'une instance se fait avec le mot clef : **new**. .. code-block:: JavaScript :linenos: :force: class Personne{ //... } personne = new Personne(); La définission d'attribut de classe se fait dans une méthode **"construtor()"**. Cette méthode est appellée automatiquement à la création d'une instance de la classe. C'est l'équivalent de la méthode **"__init__()"** en Python. La définition d'attribut ou l'appel d'une méthode depuis une autre méthode de la classe doit être précéder de **"this"**. c'est l'équivalent de **"self"** en Python. .. code-block:: JavaScript :linenos: :force: class Personne{ constructor(nom, prenom){ this.nom = nom; this.prenom = prenom; } } Héritage de classe ^^^^^^^^^^^^^^^^^^ L'héritage d'une classe se fait par lajout du terme **"extends" suivie du nom de la calsse mère** dans la déclaration de classe. Il faut égallement appeller la méthode **"super()"** dans la méthode **"constructor()"** de la classe fille. .. code-block:: JavaScript :linenos: :force: class Homme extends Personne{ constructor(nom, prenom){ super(nom, prenom); //Equivalent de Personne.constructor(nom, prenom) this.sexe = "H"; } log(){ console.log(`nom : ${this.nom}, prenom : ${this.prenom}`); } } var personne = new Homme("Bond", "James"); personne.log(); super() +++++++ :Liens_Web: * `super() : MDN web docs`_ .. _`super() : MDN web docs`: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/super Le mot-clé super est utilisé afin d'appeler ou d'accéder à des fonctions définies sur l'objet parent. Lorsqu'il est utilisé dans un constructeur, le mot-clé super est utilisé seul et doit apparaître avant le mot-clé this. Ce mot-clé peut également être utilisé afin d'appeler des fonctions sur un objet parent. Import / Inclusion de module ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Un module représente un fichier qui doit être importer dans un autre fichier. Il est possible, mais déconseiller, de faire import de ces modules directement dans le fichier HTML. Cette approche impose de connaitre à l'avance toutes les dépendances et donc nous oblige à inserer tous les fichiers dans l'ordre. De plus le fichier HTML est alors surchargé ce qui peux le rendre difficile à maintenir. .. code-block:: html :linenos: :force: > Pour éviter ces problèmes, il faut créer des modules en choisissant les éléments à exposer à l'Aide du termes **"export"**. Le ficher deveint un module à ce moment là. Il est possible d'exporter plusieurs éléments en les séparant par des virgules. .. code-block:: JavaScript :linenos: :force: //module "personne.js" class Personne{ constructor(nom, prenom){ this.nom = nom; this.prenom = prenom; } log(){ console.log(`nom : ${this.nom}, prenom : ${this.prenom}`); } } export {Personne}; L'utilisation de ces modules se fait à l'aide de la commande **"import [...] from [...]"**. .. code-block:: JavaScript :linenos: :force: // Module "Homme" import {Personne} from "./personne.js"; class Homme extends Personne{ constructor(nom, prenom){ super(nom, prenom); //Equivalent de Personne.constructor(nom, prenom) this.sexe = "H"; } log(){ super.log(); console.log("C'est un homme !"); } } export {Homme}; IL est conseiller d'importer tous les modules dans un seul fichier. .. code-block:: JavaScript :linenos: :force: import {Personne} from "./personne"; import {Homme} from "./homme"; var personne = new Personne("Gabin", "Jean"); personne.log(); var personne2 = new Homme("Bond", "James"); personne2.log(); On peux ensuite importer Ce fichier dans une balise **"script"** de type **"module"** dans le fichier html. .. code-block:: html :linenos: :force: Importer du CSS --------------- Si on importe les fichier JavaScript sans préciser l'extention, c'est l'inverse lorsque l'on doit inserer du CSS. .. code-block:: JavaScript :linenos: :force: import {Personne} from "./personne" import styles from "./css/monSuperCSS.css" .. glossary:: DOM Le DOM (Document Object Model) est une API qui réprésente et interagit avec tous types de documents HTML ou XML. Le DOM est un modèle de document chargé dans le navigateur. La représentation du document est un arbre nodal. Chaque nœud représente une partie du document (par exemple, un élément, une chaîne de caractères ou un commentaire). Le DOM est l'une des API les plus utilisées sur le Web parce-qu'il autorise du code exécuté dans un navigateur à accéder et interagir avec chaque nœud dans le document. Les nœuds peuvent être créés, déplacés et modifiés. Des auditeurs d'évènements (event listeners) peuvent être ajoutés à des nœuds et déclenchés par un évènement donné. À l'origine, DOM n'était pas standardisé. Il ne l'a été que lorsque les navigateurs ont commencé à implémenter JavaScript. Le DOM qui découle de cette période initiale est parfois appelé DOM 0. À l'heure actuelle, le W3C édicte les spécifications de la norme DOM. Source : `DOM sur MDN web docs`_ Voir aussi : `DOM sur Wikipedia`_ .. _`DOM sur MDN web docs`: https://developer.mozilla.org/fr/docs/Glossaire/DOM .. _`DOM sur Wikipedia`: https://fr.wikipedia.org/wiki/Document_Object_Model .. glossary:: AJAX Le JavaScript et XML asynchrone (AJAX) est une pratique de programmation qui consiste à construire des pages web plus complexes et plus dynamiques en utilisant une technologie connue sous le nom de XMLHttpRequest. AJAX vous permet de mettre à jour simplement des parties du DOM d'une page web HTML au lieu de devoir recharger la page entière. AJAX vous permet également de travailler de manière asynchrone, c'est-à-dire que votre code continue à s'exécuter pendant que la partie de votre page web essaie de se recharger (par opposition à la méthode synchrone qui bloque l'exécution de votre code jusqu'à ce que la partie de votre page web ait fini de se recharger). Avec les sites web interactifs et les standards modernes du web, AJAX est progressivement remplacé par des fonctions dans les cadres JavaScript et l'API standard officielle Fetch API. Source : `AJAX sur MDN web docs`_ Voir aussi : * `AJAX sur WIKIPEDIA`_ * `AJAX, guide pour les développeurs du WEB`_ .. _`AJAX sur MDN web docs`: https://fr.wikipedia.org/wiki/Ajax_(informatique) .. _`AJAX sur WIKIPEDIA`: https://fr.wikipedia.org/wiki/Ajax_(informatique) .. _`AJAX, guide pour les développeurs du WEB`: https://developer.mozilla.org/fr/docs/Web/Guide/AJAX #### .. index:: single: JSX single: JavaScript; JSX single: React; JSX single: WEB; JSX --- JSX --- :Liens_Web: * `Les bases du JSX`_ * `Introduction à JSX`_ * `JSX dans le détail`_ .. _`Les bases du JSX`: https://www.apprendre-react.fr/tutorial/debutant/jsx/ .. _`Introduction à JSX`: https://fr.reactjs.org/docs/introducing-jsx.html .. _`JSX dans le détail`: https://fr.reactjs.org/docs/jsx-in-depth.html Definission de JSX ================== Le JSX est l'encapsulation d'un pseudo HTML dans du Javascript. cela permet donc de simplifier l'écriture. C'est ce que l'on appel du *"sucre syntaxique"*. On écris le html directement dans le code JavaScript, ce qui nous permet d'y inclure directement des composants React. .. code-block:: JavaScript :linenos: :force: //Expression en JSX const element = (

Je s'appel Groot !

); //Expression en REACT const element = React.createlement( 'h1', {className: 'greeting'}, 'Je s'appelle Groot !' ); Ces deux expressions sont équivlente. Il est possible d'ajouter des commentaire dans une expression JSX. Les commentaire s'écrivent comme pour le JavaScript mais entourés d'accolades. .. code-block:: JavaScript :linenos: :force: const element = (

{/* un super commentaire bien pertinent */} Je s'appelle Groot !

); Interpréter le JSX dans un navigateur ===================================== Le JSX n'est pas nativement interpréter par les navigateurs. Pour interpréter le JSX dans le navigateur, il faut le prévoir dans le HTML en ajoutant une la bibliothèque **"Babel"** au moyen de la balise **. Il faut également inclure l'attribut *type="text/babel"* dans la balise script contenant le JSX. .. code-block:: html :linenos: :emphasize-lines: 10, 17 :force:
.. warning:: L'inclusion de Babel pour interpréter le JSX ralentie le programme. En effet, cela ajoute une étape de traduction supplémentaire au processus. L'inclusion de Babel est donc a reserver à la phase de **Developpement**. En phase de **production** on utilisera d'autres outils tel que **Webpack** pour créer un package. Details syntaxique ================== * Le mot clef **'class'** habituellement utilisé dans le html ne peut pas être utilisé en JSX car c'est égallement un mot clef utilisé en Javascript. Dans les expressions JSX, ce mot clef est remplacé par **"className"**. * Les mots clefs composés (séparé par "_") utilisés en CSS sont systématiquement remplacé par le formatage en **lowerCamelCase** * JSX (et donc React) considère les composants commençant par des lettres minuscules comme des balises :term:`DOM`. Par exemple,
représente une balise HTML div, mais représente un composant, et exige que l’identifiant Welcome existe dans la portée courante. * Toutes les balises auto-fermantes doivent être fermées avec "/" avant le ">" .. code-block:: html :linenos: :emphasize-lines: 1, 4 :force: * Le JSX n'accepte de retourner qu'un seule élément parent à la fois .. code-block:: html :linenos: :force: // Code en erreur import React, { Component } from 'react' class App extends Component { render() { return ( {/* Premier composant parent */}

Je s'appelle Groot !

{/* Second composant parent (Interdit !) */}

Je s'appelle Pierre

) } export default App Pour eviter ce problème, on import "Fragment" depuis React et on entoure le JSX d'une balise "" .. code-block:: html :linenos: :force: // Code valide import React, { Component, Fragment } from 'react' class App extends Component { render() { return ( {/* Premier composant parent */}

Je s'appelle Groot !

{/* Second composant parent (Interdit !) */}

Je s'appelle Pierre

) } export default App #### .. index:: single: React single: JavaScript; React single: MERN; React single: WEB; React -------- React.js -------- :Liens_Web: * `Site officiel React`_ * https://reactjs.org/docs/cdn-links.html # Doc officiel permettant le téléchargement des liens CDN à inserer dans la page HTML .. _`Site officiel React`: https://fr.reactjs.org/docs/getting-started.html React est une bibliothèque Javascript, utilisée pour créer des composants d'affiche. Dans le modèle MVC, React correspond à la **Vue**. Pour créer une application avec React, on va créer des composants (des classes ou des fonctions) qui seront ensuite assemblé pour former l'application finale. Les composant React sont réutilisable. **React utilise un DOM virtuel** Lors de l'utilisation de bibliothèques telles que JQuery nous manipulons directement les éléments HTML de la page, c'est à dire le DOM. React ne manipule pas le DOM directement, mais une copie interne de celui-ci (appellé DOM Virtuel), et produit les modifications d'affichage uniquement lorsque cela s'avère nécessaire. **React Native** (une variante de React) permet de créer des application IPhone ou Android. React affiche sont propre html au travers du **JSX**. On s'interdit donc d'écrire du html dans le ficher ".html" à l'éxecption du code minimum et des balises
qui accueilleront le html de React. React est composé de 2 bibliothèques JavaScript à inserer dans la page HTML : * **React** : Correspond à React lui même qui permet de créer des composant d'affichage réutilisable. * **ReactDOM** : Extention permettant d'effectuer le rendu, dans une page HTML, les composants créer avec React. Attention, les deux bibliothèques sont fournie en version **"development"** et en version **"production"**. Le code minimale d'une page est donc : .. code-block:: html :linenos: :force:
Getting started =============== :Liens_Web: * `Package create-react-app`_ .. _`Package create-react-app`: https://github.com/facebook/create-react-app **Create React App** est un paquet qui permet de créer l'arborescence et d'installer toutes les dépendances nécéssaires. e paquet doit être installer globallement. .. code-block:: shell :linenos: :force: npm install -g create-react-app # Créer ensuite un nouveau projet npx create-react-app [my-app] # Attention, les noms des projets doivent être écris en # minuscule uniquement. cd [my-app] npm start Versionning et récupération de projet ------------------------------------- Lorsqu'un projet react est créer, il est contient un fichier '.gitignore' qui exclue le dossier "node_modules". Le dossiers "node_modules" contient toutes les dépendances de React. Ces dépendances sont listées dans le fichiers "package.json". Si le projet est récupérer d'un dépot distant comme Github par exemple il faut alors installer les dépendances du projet. .. code-block:: shell :linenos: :force: cd [my-app] npm install #lecture du fichier "package.json" pour identifier les dépendances à installer Composants (component) ====================== Les types de component ---------------------- Il existe 2 types de composants. Les fonctions (appellées **fonctions composants**) et les classes. Une **fonction composant** est une fonction Javascript qui n'accepte qu'un seul argument appellé **props** qui signifie "propriétés". Il peut ne pas y avoir de props. Ce composant doit obligatoirement retourner quelque chose .. code-block:: JavaScript :linenos: :force: // fonction composant import React from 'react' function Welcome(props){ return

Bonjour, {props.name}

; } } On peut également utiliser une classe ES6 pour définir un composant. .. code-block:: JavaScript :linenos: :force: // class import React from 'react' class Welcome extends React.Component{ render() { return

Bonjour, {this.props.name}

; } } // Alternative : import de React.Component à l'aide du destructuring import React, { Component } from 'react' class Welcome extends Component { render() { return

Bonjour, {this.props.name}

; } } Ces 2 composants (la fonction et la classe) sont équivalents. Une classe doit systématiquement avor une méthode **"render(){return()}"** c'est cette méthode qui modifie le DOM virtuel. Choix d'un composant ? Fonction : Classe ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Le choix du type de composant doit se faire en se posant la question : *Est ce a un état (à conserver ou à modifier) ?* On parle de **Stateful** si la réponse est : NON, on parle de **Stateless** * Une classe est (ou peut l'être) Stateful. * Une fonction est toujours Stateless. La philisophie de React est d'avoir des composants le plus simples possible pour pouvoir les réutiliser plus facillement. Les fonctions sont donc à privilégier le plus souvent possible si le composant est Stateless. Si le composant est Stateful, il n'y à pas le choix, seule une classe répond à ce critère. Rendu d’un composant : Comment lier React au DOM ? -------------------------------------------------- Pour lier une application au DOM, il faut utiliser le package ReactDOM et la fonction render avec en paramètres, le composant racine de l'application et le noeud du DOM auquel il sera attaché. .. code-block:: JavaScript :linenos: :force: ReactDOM.render( , docment.getElementById('root') ); Les éléments peuvent soit représenter un éléments du DOM : .. code-block:: JavaScript :linenos: :force: const element =
; soit représenter un élément définis par l'utilisateur : .. code-block:: JavaScript :linenos: :force: const element = ; Lorsque React rencontre un élément représentant un composant défini par l’utilisateur, il transmet les attributs JSX à ce composant sous la forme d’un objet unique. Nous appelons cet objet **"props"**. **Le rendu** se fait en appellant **ReactDOM.render()**. .. code-block:: JavaScript :linenos: :force: function Welcome(props){ return

Bonjour, {props.name}

; } const element = ; ReactDOM.render( element, document.getElementById('root') ); Détail du déroulement de l'exemple précedent : #. On appelle **ReactDOM.render()** avec l’élément créer par . #. React appelle le composant Welcome avec comme props {name: 'Sara'}. #. Notre composant Welcome retourne un élément

Bonjour, Sara

pour résultat. #. React DOM met à jour efficacement le DOM pour correspondre à

Bonjour, Sara

. Parcourrir un tableau et l'afficher sous forme de liste ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: JavaScript :linenos: :force: {/* JavaScript Object */} var d= {elm1: "Je s'appelle Groot !", elm2: "Je s'appelle Pierre !", eml3: "Je s'appelle atarte"} {/* Creation of an array from keys of the "d" object */} var dKeys = Object.keys(d) console.log("dKey : ", dKeys) {/* Browsing the "dkeys" array with the map function. The map function use a callback function. Each item (dkey) is given as the unique key ID : ("item", "unique key")=>{...} */} var ul = React.createElement("ul", null, dKeys.map( (dKey, dkey)=>{ return ( React.createElement("li", null, d[dKey]) ) } ) ) console.log(ul) {/* the "ul" function is given to the render */} ReactDOM.render(ul, document.getElementById("app")) Extraire des composants ----------------------- En règle générale, les nouvelles applications React ont un seul composant **App** à la racine. C'est l'équivalent d'une fonction *main()*. Pour faciliter la maintenance et la portabilité des éléments, il est conseiller d'avoir un composant **App** le plus simple possible. Pour cela, on doit isoler, chaque fois que c'est possible, les éléments en composants plus petits (et monotache). .. code-block:: JavaScript :linenos: :force: function Comment(props) { return (
{props.author.name}
{props.author.name}
{props.name}
{formatDate(props.date)}
); } Si on définit séparément les composant **Avatar** et **UserInfo**, on pourra alors simplifier le composant **Comment** : .. code-block:: JavaScript :linenos: :force: // Composant "Avatar" function Avatar(props) { return ( {props.user.name} ); } // Composant "UserInfo" function UserInfo(props) { return (
{props.user.name}
); } // composant "Comment" function Comment(props) { return (
{props.text}
{formatDate(props.date)}
); } .. rubric:: Convertir une fonction en classe Il est possible de convertir une fonction en classe en quelques étapes: #. Créez une classe, avec le même nom, qui étend React.Component (ou simplement Component si on l'a importer en destructuring {component}). #. Ajoutez-y une méthode vide appelée render(). #. Déplacez le corps de la fonction dans la méthode render(). #. Remplacez props par this.props dans le corps de la méthode render(). la méthode render n'a q'un seul élément : 'return' suivie d'un bloc JSX entouré de parenthèses. #. Supprimez la déclaration désormais vide de la fonction. .. code-block:: JavaScript :linenos: :force: //Fonction Clock function Clock(props) { return (

Bonjour, monde !

Il est {props.date.toLocaleTimeString()}.

); } //Classe Clock après transformation class Clock extends React.Component { render() { return (

Bonjour, monde !

Il est {this.props.date.toLocaleTimeString()}.

); } } .. rubric:: Les props sont en lecture seule Une fonction est dite "pure" si elle ne tente pas de modifier ses entrées et retourne toujours le même résultat avec les même entrées. .. code-block:: JavaScript :linenos: :force: // Une fonction pure (qui ne modifie pas ces propres entrées) function sum(a, b) { return a + b; } // Une fonction impure (qui modifie ces propres entrées) function withdraw(account, amout) { account.total -= amount; } React applique une règle stricte : **"Tout composant React doit agir comme une fonction pure vis-a-vis de ses props"**. Les fonctions composants ne pouvant manipuler que des props, on les utilisent lorsque notre composant ne modifie pas sont état. On parle de **Composant Stateless**. Lorsqu'un composant doit modifier son état, on utilise une classe. .. code-block:: JavaScript :linenos: :force: const famille = { membre1: { nom: 'Pierre, age: 42, type: 'humain' }, membre2: { nom: 'Tartine' age: 8, type: 'chat' } } class App extends Component { // 'state = { famille }' en version destructuration // 'state = { famille : famille }' en version normal state = { famille } render() { const {titre} = this.props const { famille } = this.state return(

{titre}

) } } props ----- :Liens_Web: * `What is 'props' and how to use it in React ?`_ .. _`What is 'props' and how to use it in React ?`: https://itnext.io/what-is-props-and-how-to-use-it-in-react-da307f500da0 .. glossary:: Props 'Props' est un mot clef spécial en React qui représente les **propriétées**. Il est **utilisé pour** **transmettre des données (propriétés) d'un composant à un autre.** Les propriétés ne sont transmisent que dans un sens : du composant parent vers le composant enfant. On parle de **'uni-directionnal flow'**. Les data transmisent par les props sont en lectures seules. Cela signifie que **les data ne doivent pas être changées par le composant** **enfant**. Si une données doit changer d'état ou de valeur, il faut utiliser les **states**. Utilisation des Props ^^^^^^^^^^^^^^^^^^^^^ Il faut se rappeler que les props sont des arguments passés aux composants. On peut résumer l'utilisation des props en 3 étapes: #. On définie un attribut et sa valeur (Data) sous la forme d'un Objet JavaScript (Dictionnaire) : {Attribut: Value}. #. On passe cet attribue à un composant enfant en utilisant 'props'. #. On effectue le rendu de la data du props. States ------ :Liens_Web: * `React JS — Understanding State`_ .. _`React JS — Understanding State`: https://codeburst.io/react-js-understanding-state-e875911e921c hooks ^^^^^ **WIP** Une alternative a setState() React-Router-DOM ================ :Liens_Web: * `gérer la navigation programmatique`_ * `faire un redirect avec le composant react-router-dom après une requête POST`_ * `Quick Start`_ : semble être la doc officiel .. _`gérer la navigation programmatique`: https://www.journaldunet.fr/web-tech/developpement/1441259-comment-gerer-la-navigation-programmatique-avec-react-router/ .. _`faire un redirect avec le composant react-router-dom après une requête POST`: https://www.journaldunet.fr/web-tech/developpement/1441289-comment-faire-un-redirect-avec-le-composant-react-router-dom-apres-une-requete-post/ .. _`Quick Start`: https://reacttraining.com/react-router/web/guides/quick-start React-routeur-dom est un paquet qui permet de rediriger vers une nouvelle url et donc d'afficher un nouveau composant en giraant l'esrpie "monopage" de React. .. warning:: A chaque changement de composant ce dernier est recharger dans le DOM. Il est donc important de **percisté les données** avec le localstorage ou une base de donnés. Dans le cas contraite toutes les données seront perdu puisque le composant sera chargé à son état initial. #### .. index:: single: Node single: JavaScript; Node single: MERN; Node single: WEB; Node ------- Node.js ------- :Liens_Web: * `Nodejs dowload`_ .. _`Nodejs dowload`: https://nodejs.org/en/download/ Node.js (ou Node) est un runtime pour Javascript. Tout comme JRE est le runtime de JAVA. Il permet à Javascript de s'executer en dehors d'un navigateur par exemple coté serveur. #### .. index:: single: NPM single: Node; NPM -------------------- NPM - Packet manager -------------------- :Liens_Web: * `Installation et découverte de npm`_ .. _`Installation et découverte de npm`: https://www.pierre-giraud.com/npm-installation-decouverte/ .. glossary:: NPM npm (Node Package Manager) est le gestionnaire de paquets officiel de Node.js. Il permet de télécharger et d’installer des paquets (encore appelés modules ou librairies) pour pouvoir les utiliser pour un projet ou au contraire de partager des paquets pour que d’autres utilisateurs puissent les utiliser. #### -------------------- Package et framework -------------------- .. glossary:: middleware Middleware are function that Express executes in the middle after incomming request and before the output. Middlewares might make changes to the request and response objet. The 'use' function registers a middleware with our Express app. With 'app.use(express.json())', the express.json() let's us retrieve data from a request via the 'body' attribute. Without this middleware, data retrieval would be much more difficult. Express.JS ========== Epress est un framework qui permet de simplifier la tache d'écriture du code d'un serveur WEB (Backside). Il nous laisse définir les routes et les actions à effectuer lorsqu'une requette HTTP arrive est qu'elle correspond à l'un des patterns que nous avons défini. les patterns utilisé dans la comparaison avec les requèttes HTTP correspondent à une expression regulière. Il est également possible de créer des middleware qui pourron être inserer dans le traitement entre la requètes HTTP (en entrée) et la réponse (en sortie). Les opérations de logging et d'authentification sont, par exemple traitées à l'aide de middleware. Babel ===== Installer babel en mode dévellopeur : .. code-block:: shell :linenos: :force: npm install --save-dev @babel/core@7 @babel/cli@7 # le "@7" signifie que l'on force l'installation de la version 7 du package. Babel est capable de plusieurs nombreuse convertion / transformation. Il y a cependant un package différent pour chacunes des taches. Le package permettant de convertir le JSX en en Javascript est : PRESET-REACT. #### -------- Weblinks -------- .. target-notes::