ReactJS – Evénements et fonctions paramétrées

Exemple avec l’événement onClick d’un bouton

Imaginons qu’en cliquant sur notre bouton, un compteur s’incrémente et s’affiche à l’écran.

Pour cela, on va assigner à l’event onClick, une fonction qu’on nommera handleIncrement. L’appel de la fonction handleIncrement ne peut pas être paramétrée.

Autrement dit, on ne peut pas écrire


<button onClick={this.handleIncrement(number)}>INCREMENT</button>

Pour passer un paramètre à la fonction (handleIncrement(number)), 2 solutions :

I Hack

Écrire une fonction sans argument, qu’on va nommer doHandleIncrement. Dans le corps de cette fonction appeler la fonction avec argument.


handleIncrement = (number) => this.setState({ count: this.state.count + number });

doHandleIncrement = ()=>{
this.handleIncrement(number)
}

<button onClick={this.doHandleIncrement}>INCREMENT</button>

II Meilleur solution

Ecrire ‘inline’ la fonction dont le corp possède la fonction avec argument.

De cette manière on évite de ré-écrire à chaque fois une fonction non paramétrée qui encapsule la fonction paramétrée.

La portée des variables et le “Hoisting”

VAR

Les variables typées var :

  1. ont une portée limitée seulement dans le cadre d’une fonction (ce n’est pas le cas dans les blocks if,for,foreach…)
  2. si la fonction a accès au context extérieur via une variable (“closure”), celle ci peut être modifiée
var a = 'World'
var a = function (){
        console.log('Hello')
        a = 'Buddy'
        var b = function (){
               console.log(a)
        }
        return b()
}
a()

Sortie

 
Hello
Buddy

Hoisting

Le Hoisting (ou hissage) élève la déclaration des variables tout en haut de l’execution de notre script.

En effet, Javascript n’est pas executé de la même manière qu’on l’écrit.

Dans l’exemple précédant, si on retourne b() avant de définir celle-ci une erreur apparait à l’execution :

 
var a = 'World' 
var a = function (){ 
        console.log('Hello') 
        a = 'Buddy' 
        return b() 
        var b = function (){ 
                console.log(a) 
        } 
} 
a() 

Sortie

TypeError: b is not a function

En effet Javascript remanie le code en déclarant les variables en haut de la fonction (c’est l’action de Hoisting) :

 
var a 
a = 'World' 
a = function (){ 
    var b //Declare b
    console.log('Hello') 
    a = 'Buddy' 
    return b() //Call b which is undefined at this step -> Error
    var b = function (){ 
            console.log(a) 
    } 
} 

En revanche, si on n’assigne pas nos fonctions à des variables, javascript Hoist (hisse) la définition de la fonction :

 
function a (){ 
    console.log('Hello') 
    var a = 'Buddy' 
    return b() 
    function b (){ 
        console.log(a) 
    } 
} 
a()

devient …

 
function a (){
    var a 
	function b (){ 
        console.log(a) 
    } 
    console.log('Hello') 
    a = 'Buddy' 
    return b()   
} 
a()

Le Destructuring

Le Destructuring ou déballage

En Javascript , le Destructing consiste à

  1. ‘déballer’ ou récupérer les élements d’un tableau ou bien les propriétés d’un objet
  2. Assigner unitairement ces éléments à des variables distincts

Exemple

function DestructureIt(fct){
    //variable a and b are assigned with split result
    [a,b] = fct('a').trim().split('|')
    console.log(a,b)
}

//Call
DestructureIt(a => a)

Sortie

a undefined

Note : quand le séparateur n’existe pas, split() renvoie undefined.

On peut encore utiliser le Destructuring afin d’assigner à des variables, les propriétés d’un objet :

var objectJH= {lastname:'Jimi', firstname:'Hendrix'}
var {lastname,firstname} = monObject
console.log(`${lastname} ${firstname}`)
Note: A condition que ces variables portent le même nom que les propriétés qui les assignent.
Si on veut attribuer un autre nom de variable on fait suivre le nom de la propriété de “:” et on indique le nouveau nom de variable (par exemple ltname et ftname) :
 
var objectJH= {lastname:'Jimi', firstname:'Hendrix'} 
var {lastname: ltname,firstname: ftname} = monObject 
console.log(`${ltname} ${ftname}`) 

Sortie

 Jimi Hendrix 

Un cas où le point virgule est important !

Le code Javascript permet une plus grande souplesse syntaxique et plus particulièrement, le developpeur peu s’aquitter de l’usage des fameux point virgule ‘;’ qui terminent chaque instructions.

Dans certains cas, le ‘;’ peu s’avérer obligatoire :


//Ce petit script affiche dans la console si 'n' est pair ou impair 
//et insére cette valeur dans le tableau associé.

let even = [], odd = []

let n = 246

console.log('n is %s', n % 2 === 0 ? 'even' : 'odd')

(n % 2 === 0 ? even : odd).push(n)

Sortie


TypeError: console.log(...) is not a function
at Object.&lt;anonymous&gt; (D:\MSO Consulting\Formations\Javascript\Docs\Samples\Server\server.js:39:1)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)

Bug

Bug à la compilation : console.log(…) is not a function.

La raison

Du fait de l’absent de ‘;’ à la fin de l’instruction console.log(…) Javascript interprète le code précédent comme l’appel d’une fonction imbriquée:

fonction()(param).push(element)

console.log('n is %s', n % 2 === 0 ? 'even' : 'odd')(n % 2 === 0 ? even : odd).push(n)

Dans ce cas précis, il est donc nécessaire d’ajouter un ‘;’ à la fin de l’instruction console.log (…)

Solution

console.log('n is %s', n % 2 === 0 ? 'even' : 'odd');
(n % 2 === 0 ? even : odd).push(n)

 

 

Map

Définition

Map à été intégré avec la cinquième version du standard ECMA-262 (ECMAScript 5). C’est une fonction qui s’applique sur un tableau.

L’idée est le que la fonction de callback fourni en argument de Map s’applique sur chacun des éléments du tableau d’origine. Sur chaque éléments de ce tableau, une opération est effectué, ainsi, au fur et à mesure que les opérations de callback se produisent sur chaque élément du tableau d’origine, chaque résultats devient un élément du nouveau tableau.

Syntaxe

var newArray = OldArray.map(callback[,thisArg])

Paramètre

Callback
La fonction de callback utilisé pour créer un élément du nouveau tableau. Cette fonction prends en paramètre 3 arguments :

  1. Valeur courante
    La valeur de l’élément courant du tableau d’origine sur lequel on applique map.
  2. Index courant [Facultatif]
    L’index de l’élément courant du tableau d’origine.
  3. Tableau d’origine [Facultatif]
    Tableau d’origine sur lequel on appel la methode map.

ThisArg
C’est la valeur à utiliser pour le context This lors de l’execution de la fonction de callback. Attention, la fonction de callback doit être écrite sous forme de fonction anonyme.
En d’autres termes, si le callback est une lambda expression, la valeure de This sera ignorée et retournera toujours le contexte global window.

Exemples

  • Callback – Utilisation de valeur et index courant
    Double les éléments situés à un indice pair et renvoi le nouveau tableau modifié.

     
    var array = [0,1,2,3,4,5,6] 
    var mappedArray = array.map((elt,i)=>(i%2===0)?elt*2:elt) 
    console.log(mappedArray) 
    //Output : [0,1,4,3,8,5,12] 
    
  • Modifier le format d’objet du tableau d’origine.

    var employees = [
    { age: 20, name: 'Dgibril Diop' },
    { age: 24, name: 'Jean Edouard' },
    { age: 56, name: 'Youssef Ziad' },
    { age: 88, name: 'John Smith' }
    ];
    
    var newEmployees = employees.map(elt=>{
    var obj = {}
    obj[elt.age]=elt.name
    return obj
    })
    console.log(newEmployees)
    //Output : 
    [ { '20': 'Dgibril Diop' },
      { '24': 'Jean Edouard' },
      { '56': 'Youssef Ziad' },
      { '88': 'John Smith' } ]
    
  • Map – utilisation de ThisArg
    Reprenons l’exemple précédent.
    En second paramètre de Map, passons un objet ayant pour propriété ‘x’ et pour valeur ‘My name is’.
    On constate que This a pour context la propriété passés en paramètre.

    var employees = [
    { age: 20, name: 'Dgibril Diop' },
    { age: 24, name: 'Jean Edouard' },
    { age: 56, name: 'Youssef Ziad' },
    { age: 88, name: 'John Smith' }
    ];
    
    var newEmployees = employees.map(function(elt){
    var obj = {}
    obj[elt.age]=this.x+elt.name
    return obj
    },{x:"My name is "})
    console.log(newEmployees)
    
    //Output :
    [ { '20': 'My name is Dgibril Diop' },
    { '24': 'My name is Jean Edouard' },
    { '56': 'My name is Youssef Ziad' },
    { '88': 'My name is John Smith' } ]
    

Array reduce

Avant d’aborder quelques exemples sur le sujet, faisons une petite synthèse de la méthode reduce, en exposant ses différents paramètres.

Définition

La méthode reduce applique une opération à chaque éléments d’un tableau.
Le résultat est stocké dans un accumulateur.

Qu’est ce qu’un accumulateur?
Nous savons que reduce s’applique sur un tableau initial qui contient sa propre liste de données.
A chaque itérations, la dernière valeur précédemment calculé est accumulé.
Le résultat final sera la dernière valeur calculé par le dernier appel de la fonction callback.

Syntaxe

array.reduce(callback,valeurInitiale[Facultatif])

Paramètres

Callback : La fonction de callback est le premier paramètre.
Celui ci se décline en 4 autres paramètres :

    1. Accumulateur
      Valeur finale à retourner
    2. Elément courant
      Valeur de l’élément courant du tableau d’origine
    3. Indice de l’élément courant [Facultatif]
      Indice de la valeur de l’élément courant du tableau d’origine.
    4. Le tableau d’origine [Facultatif]
      Le tableau d’origine sur lequel on a appelé la méthode reduce.

Valeur initiale [Facultatif]
Si la valeur initiale est fourni, alors reduce exécutera la fonction de callback à partir de l’indice 0.
Si au contraire la valeur initial n’est pas fourni, alors reduce exécutera la fonction de callback à partir de l’indice 1, (l’indice 0 sera considéré comme valeur initiale)

Exemples

    • Somme d’un tableau (reduce sans valeur initial en paramètre)
       
      var array = [2,4,6,8] 
      var result = array.reduce((accumulator,currentItem)=>accumulator+currentItem)
      //Output : 20 
      
    • Somme d’un tableau (reduce avec valeur initial)
       
      var array = [2,4,6,8]
      var initialValue = 100
      var result = array.reduce((accumulator,currentItem)=>accumulator+currentItem,InitialValue) 
      //Output : 120 
      
    • Dernier fichier d’un repertoire.
      Récupérons le fichier le plus récent d’un répertoire MyFolder.

      //GetMaxFile Get most recent file stored in MyFolder
      function GetMaxFile(){
      var files = fs.readdirSync(MyFolder)
      return files.reduce((item,max)=>item>max?item:max)
      }
      
    • Suites de Fibonacci
       
      function Fibonacci(sequenceSize){
          return new Array(sequenceSize).fill(0).reduce(
           (arr,_,i)=>{arr.push((i>=1)?i:arr[i-2]+arr[i-1])
           return arr},[])
          );
      }
      
      console.log(Fibonacci(7))
      //Output : [0,1,1,2,3,5,8]
      

      Suite Fibonacci 2

       
      function Fibonacci_1(sequenceSize){ 
      const fibo = new Array(sequenceSize).fill(0) fibo.reduce((_,__,i)=>(fibo[i]=(i>=1)?i:fibo[i-2]+fibo[i-1])) 
      return fibo 
      } 
      

Note : Les caractères simples, et doubles underscores (parfois mis en paramètre des callback) illustrent le fait que je  survole ces paramètres.