Formation « Créer des blocs avec Gutenberg »

Notions fondamentales de JSX et ESNext

Lecture : 11 minutes • 0

Lors de la création de nos blocs on va apercevoir des façons de coder parfois très particulières, voire carrément bizarres. C’est tantôt la faute à ESNext, et tantôt la faute à React. Dans ce cours je vais vous expliquer ces syntaxes et leurs bénéfices.

Ce cours est très important si comme moi, vous attaquez Gutenberg sans avoir jamais fait de JS pour des apps web et du React auparavant.

Vous allez voir des choses nouvelles et tordues, alors prenez un petit café, thé, Coca, Redbull ou peut importe la substance qui peut vous tenir éveiller, car on s’attaque à un gros morceau. Et ce ne sont pas les quelques GIF animés que j’ai placés ça et là qui vont aider à mieux faire passer la pilule !

Mais après ça promis, c’est que du bonheur !

Les syntaxes ESNext

À partir de 2015, le langage Javacript, via sa spécification EcmaScript, a enfin commencé à évolué. Le langage souffrait de certaines lourdeurs qu’il était temps de corriger.

La première série d’évolutions s’est appelée ES2015, puis ES6, ES7, et maintenant au lieu de compter, on parle simplement d’ESNext.

Sans trop entrer dans les détails, je vais simplement passer sur les syntaxes qui vont nous êtres utiles :

Définition de variables : Var, Let et Const

Une des premières nouveautés de Javascript a été la façon dont on peut appeler des variables. Habituellement on déclarait toujours une nouvelle variable avec le mot-clé var.

La portée (le scope en anglais) de var est énorme et du coup il est très facile de polluer son application.

Déclarer une variable avec let permet de limiter sa portée dans la fonction ou le bloc (un if, un for…) dans lequel elle a été déclarée. Du coup on va désormais préférer utiliser letface à var, car il convient dans la grande majorité des cas.

Enfin, lorsque l’on déclare une variable qui au final ne va pas varier, on utilise const. On va beaucoup l’utiliser par ailleurs, notamment quand on va importer des classes de Gutenberg ou des dépendances.

JS
script.js

Tout comme varlet et const sont « vus » par les fonctions déclarées en dessous : dans la fonction test() on peut bien afficher la valeur de a, b et c.

Par contre comme d est défini dans le if, il est impossible d’y accéder de l’extérieur.

Pour faire simple, si on déclare quelque chose qui ne va pas changer, on utilise const. Si on déclare une variable, en général let fera l’affaire.

La fonction double flèche

Pour déclarer une fonction, jusque là on faisait simplement function truc() { … }. Rien de plus simple. Mais désormais on utilise la double flèche, ou fat arrow en anglais et ça ressemble à ça :

JS
script.js

Cela permet d’être plus concis et c’est plus court à écrire. Ma foi. Notez que l’on stocke la fonction dans une variable via l’utilisation du mot-clé const.

Lorsqu’il n’y a qu’un seul paramètre attendu, on peut ne pas mettre les parenthèses après le =.

Bon en vrai il y a aussi un autre avantage mais je ne vais pas trop m’attarder dessus : en JS on utilise beaucoup le mot-clé this pour faire référence à l’objet qu’on est en train de manipuler, et quand on le passe dans une fonction (par exemple un événement) this ne fait plus référence à l’objet mais à l’événement. Du coup auparavant il fallait bricoler un peu. Cette nouvelle notation conserve la bonne référence à this.

Je ne m’étend pas plus sur le sujet mais si vous voulez tout comprendre sur les fonctions en JS, je vous conseille ce superbe article de Sitepoint.

Donc n’oubliez pas, dès que vous voyez dans un code une flèche => , c’est qu’il y a une déclaration de fonction !

La concaténation simplifiée

En JS la concaténation a toujours était un petit peu chiante à faire. Mais désormais on a une méthode pour le faire simplement. Il faudra utiliser les guillemets renversés (ou backtick en anglais, situé près de la touche Entrée).

JS
script.js

Au final c’est un peu comme en PHP avec les guillemets doubles (doubles quotes) !

De plus il est désormais tout à fait possible d’écrire une chaine sur plusieurs lignes (alors qu’auparavant il fallait absolument séparer avec un + entre chaque ligne.

L’import de modules

Javascript se rapproche désormais d’autres langages de programmation comme Java ou Python et permet d’importer d’autres modules ou dépendances afin de les utiliser.

JS
script.js

Dans cet exemple, j’appelle des fonctions issues de WordPress donc j’aurais besoin dans mon code. registerBlockType me permettra de déclarer mon bloc, et la fonction __ permettra de traduire les chaines de textes. Mais on va voir tout ça en détails.

Ensuite, en ligne 4, j’importe la feuille de style : cela permettra d’indiquer à Webpack que j’en aurais besoin lors de la compilation (elle n’a donc aucun intérêt direct pour l’exécution du code JS qui suit).

Alors attention : ce n’est pas à proprement parler un import d’un autre fichier comme le include() de PHP, c’est simplement une référence pour dire que l’on va utiliser des éléments de ces imports.

Si je ne le fait pas j’aurais une erreur du navigateur qu’il me dit que par exemple classnames n’est pas défini.

L’assignation destructurée

Comme on va le voir on utilisera souvent des objets et des sous-objets dans notre code. On va notamment récupérer les données de nos blocs qui seront stockées dans un objet props, puis un sous-objet attributes.

JS
script.js

Avec l’assignation déstructurée on indique à JS que l’on veut extraire les éléments, ou seulement une partie d’entre-eux. C’est un peu comme un extract() en PHP, mais là on ne récupère que ce dont on a besoin.

Dans cet exemple je récupère 2 des 4 valeurs de props.attributes et au lieu d’utiliser props.attributes.number, j’utilise simplement number dans mon code.

Cela permet aussi dès le début du code de tenir un inventaire des objets dont on va faire usage par la suite.

D’ailleurs si vous utilisez VSC, vous pourrez même voir les données que vous n’utilisez pas, car elles apparaitront en foncé :

extraction de variables JS. 2 ne sont pas utilisées et apparaissent plus foncées
className et isSelected ne sont pas utilisées dans la suite de mon code

On va beaucoup utiliser cette écriture lors de cette formation, c’est pour cela que je tenais à vous la montrer.

Les classes

Les classes permettent une programmation orientée objet (POO) comme dans tous les langages de programmation.

Jusqu’à récemment JS n’avait pas exactement cette approche par classe. C’est aujourd’hui corrigé. Lorsque l’on fait du React, chaque composant de notre application sera représenté par une classe. J’en reparle un peu plus bas.

Voici une classe représentant un composant que j’ai appelé Gmap :

JS
script.js

Le mot clé export permet de rendre cette classe (et donc ce composant dans le cas de React) disponible ailleurs, il suffira alors de l’importer avec import, que l’on a vu un peu avant.

Vous verrez parfois certains développeurs déclarer simplement la classe et faire le export default à la fin du fichier. C’est une autre façon de l’écrire mais sachez que ça revient exactement au même.

Notez enfin que dans une classe on n’est pas obligé de mettre const avant la déclaration d’une fonction.

L’assignation simplifiée

Parfois quand on assigne des valeurs à un objet, on a tendance à se répéter inutilement : la clé et la valeur ont le même nom. Heureusement en ESNext on peut simplifier cela :

JS
script.js

Dans le premier exemple on cherche à assigner la valeur de city dans un objet dont la clé sera également city. L’écriture simplifiée permet d’éviter la répétition.

Pareil pour les composants React. On va très souvent leur passer en paramètre des valeurs et des fonctions, et au lieu d’assigner une par une chaque valeur, on peut utiliser l’écriture simplifiée.

Notez dans ce cas la présence des ...{} qui permet d’indiquer à React que l’on veut une écriture attribut=valeur.


Voilà pour ESNext ! J’ai vraiment essayé de simplifier pour ne pas trop vous remplir la tête. Je me suis essentiellement attardé sur les cas que l’on va rencontrer lors du développement de blocs.

Maintenant voyons quelques syntaxes spécifiques à React :

Les syntaxes React

En réalité, les syntaxes que je m’apprête à vous montrer restent des syntaxes JS mais que l’on croise plus particulièrement en JSX dans React.

Du HTML dans du JS !

La première chose à savoir c’est qu’un composant React dispose d’une fonction render() dans laquelle on va retourner du HTML, ce qui n’est pas possible avec du JS natif.

Voici à quoi peut ressembler le render d’un composant React :

JSX
index.js

D’une ligne à l’autre on passe de Javascript à HTML, sans crier gare ! Et à la manière d’un langage de templating on peut afficher une variable grâce aux accolades !

D’ailleurs je ne sais pas si vous avez remarqué mais on utilise pas le mot class  pour appeler une classe CSS dans la div mais className, parce que mine de rien class est un mot-clé réservé du langage Javascript et à la compilation ça causerait des erreurs. Du coup React a créé le substitut className.

Les composants React

Comme on l’a vu un composant React est avant tout une classe, qui va être un peu spécifique. Et le plus fun là dedans c’est que l’on va pouvoir appeler ce composant via une balise HTML. Imaginons que j’ai une liste de tâches qui va appeler une tâche, je n’aurais qu’à appeler la balise <Task /> (je vous rappelle que cela sera compilé en du vrai JS et HTML à la fin).

JSX
index.js
JSX
task.js

Dans index.js, j’appelle mon composant Task en l’important, et lors du render()j’appelle la balise <Task /> pour indiquer que c’est ici que je veux afficher mon composant.

Cela permet de bien découper mon application en plusieurs composants, et d’aérer un peu le code : chaque composant embarque ses propres fonctions. Et on ne se gênera pas pour le faire, afin de garder notre code super lisible !

Enveloppez vos composants React dans un conteneur

React n’aime pas que vous rendiez un composant qui contient plusieurs balises HTML concomitantes. La règle ici est simple : lorsque vous rendez du code via la fonction render(), assurez-vous d’avoir toujours un bloc englobant :

JSX
index.js

Si vous faites l’erreur, vous serez vite rappelés à l’ordre par le compilateur avec ce message d’erreur :

Balises adjacentes JSX non supportées dans React
L’erreur « Adjacent JSX elements must be wrapped in an enclosing tag »

Le ternaire dans le template

Vous connaissez l’opérateur ternaire, qui permet de faire un if et juste derrière dire : si c’est vrai j’affiche ceci et si c’est faux j’affiche cela. En PHP il se présente comme ça :

PHP
index.php

Et bien on va utiliser un peu la même approche en JSX, pour par exemple afficher quelque chose lorsqu’une condition est remplie, et autre chose si elle ne l’est pas :

JSX
index.js

Dans cet exemple on regarde si on a défini un postID : si oui on va afficher le sous-composant <Post />, et sinon on va afficher un message qui incite à d’abord aller sélectionner un article.

Notez bien que l’on empacte nos deux possibilités entre des parenthèses, dans lesquelles on balance directement du HTML. Et il ne faut pas oublier d’entourer le tout d’accolades.

Bon l’exemple ici est simple mais ça peut vite devenir vite le casse-tête !

Warning

C’est souvent ici que se trouve la plus grande cause d’erreur quand on débute car à accumuler les parenthèses et les apostrophes, on s’y perd vite. C’est un des aspects de React que j’apprécie surement le moins.

La double négation

Allez un dernier what the fuck pour la route et après promis, on repasse sur des choses bien plus simples. Je pense que vous venez de vivre le cours le plus chiant de la formation, mais c’était un mal nécessaire.

Dans mes exemples vous allez souvent voir quelque chose comme ça :

JSX
index.js

C’est la double négation !

Selon moi c’est l’exemple le plus WTF que j’ai pu voir dans React. Et on a le droit à la double dose : premièrement, on met une double négation. Si j’avais mis qu’un seul point d’exclamation on aurait tout de suite compris que je cherchais à faire quelque chose quand la condition n’est pas remplie.

Mais là pourquoi 2 ? Puisque que l’on cherche à faire quelque chose quand la condition est valide alors pourquoi ne pas simplement rien mettre ?

Et bien en fait c’est une astuce pour garantir d’avoir un true / false à tous les coups. Selon les cas une valeur JS peut être null, false, undefined

La double négation permet de dire que, peut importe l’état, si ce n’est pas true, alors c’est false. Cela nous évite de devoir tester le type de la variable, voir si elle existe… et donc nous fait gagner du temps.

En clair : c’est un moyen pratique pour nous permettre de forcer le test d’un booléen.

Mr Bean aussi trouve que c’est bizarre !

Mais ce n’est pas tout ! Vous avez vu juste après le ‘et’ représenté par &&, que l’on utilise habituellement dans un if. Eh bien là on l’utilise sans if !

Ici si je traduis la ligne 3 en français j’obtient : si le bloc est focus alors j’affiche l’inspecteur.

En fait comme on est dans un return() il faut savoir que l’on n’a plus accès à nos amis les if / else. C’est pour ça que l’on triche avec des syntaxes un peu exotiques.

En alternative et pour rester classique, on pourrait tout à fait écrire notre test dans le render(), avant le return(), et stocker le résultat dans une variable.

Prenons l’exemple d’un if : le && exécute la suite seulement si le premier bloc est valide :

JS
index.js

Là c’est plutôt clair ! Si A est supérieur à 4 alors on passe dans le deuxième bloc pour vérifier si B < 10. Si la première condition n’était pas remplie alors on ne serait pas allé plus loin.

Eh bien dites-vous qu’en JS on peut faire la même chose en dehors d’un if, après tout pourquoi pas ! Dans notre exemple précédent la deuxième partie après && n’est cette fois pas un test, mais une commande à exécuter. Dans ce cas on demande l’affichage d’un template ou d’un composant, et c’est tout à fait légitime de le faire.

Donc ce qu’il faut retenir ici c’est que !! props.focus && ( ... ) se traduit par si le bloc est focus alors j’affiche ce que je met entre les parenthèses.

Question compatibilité ?

Alors bien entendu ces notations sont modernes et la question de la rétrocompatibilité vient se poser. Si vous utilisez Babel il n’y aura aucun souci car il compile tout cela dans un code JS standard (mais moins beau à la lecture).

Dans notre cas Babel est bien embarqué dans create-guten-blocks donc on peut utiliser toutes ces écritures sans souci.

Si vous voulez en savoir plus sur l’ESnext, voici quelques articles qui listent toutes les nouveautés :


Allez vous avez bien mérité une petite pause ! Lors de mon apprentissage je n’ai pas assimilé tout de suite toutes ces nouvelles notions. Je tenais simplement à vous les présenter pour être prêt quand vous allez les rencontrer dans la nature.

Pour moi c’était la partie la plus compliquée car je n’avais jamais réellement fait de React auparavant, mais une fois ces bases maitrisées la création de blocs avec Gutenberg sera un vrai plaisir !

N’hésitez pas à revenir voir ce cours lorsque l’on aura attaqué le développement. Pour l’instant c’est purement théorique et ça peut paraitre nébuleux, mais d’ici quelques cours, une fois les mains dans le code, une petite révision des explications peut s’avérer utile !

On va maintenant terminer ce chapitre par un exemple écrit à la fois en ESNext + React et en JS natif afin de comparer le code.

0

Questions, réponses et commentaires

Laisser un commentaire