Javascript est un langage connu aujourd’hui pour la diversité de ses librairies et de ses frameworks. Diversité grandissante notamment à cause de l’évolution de la complexité des sites/applications web, qui pousse à structurer de plus en plus le code javascript.

Aujourd’hui, on peut trouver des frameworks permettant d’implémenter les architectures MVVM ou MVC (Ember, Backbone, Angular…).

ReactJs, quant à lui, propose une approche bien particulière sur la manière de définir une vue. Le but de ce post sera d’avoir un petit aperçu de l’utilisation de cette librairie.

Où se situe Reactjs dans tout ça ?

En réalité, React n’est pas tout à fait comparable à un Backbone ou à Angular. Il est possible de combiner Backbone et Reactjs. Reactjs à lui seul ne permet pas d’implémenter une architecture MVC ou MVVM.

En résumé, à partir du moment où on est côté client (Web), on a des données JSON (reçues via un service Web/REST, par exemple), et dès que l’on souhaite les afficher dans un format HTML, on peut faire appel à React.

On pourrait comparer React à des moteurs de templating tels que underscore.js ou mustache.js…

Mais encore une fois, c’est un peu différent =)

Concrètement, c’est quoi ReactJs ?

ReactJs est une simple librairie javascript, au même titre que Jquery ou Knockout. Et comme beaucoup de librairies javascript, l’usage de Reactjs nécessite l’inclusion d’un js (oui un seul =) )
Voici un fichier minimal permettant d’utiliser l’api de Reactjs.

<script src="./chemin-vers-la-librairie/react.js"></script>

A quoi sert l’API exposée par ReactJs ?

ReactJs est une librairie orientée composants. L’API exposée va essentiellement servir à créer des composants graphiques.

Le principe avec ReactJs est assez simple. On crée un arbre de composants et on l’associe à un élément du DOM.

Le principe le ReactsJs

Un composant peut avoir des propriétés, il peut avoir ou non des composants fils, ou tout simplement du contenu.

Voici un exemple de composant simple créé avec ReactJs

var component = React.createElement("div", {className: "div-class"}, "hello", React.createElement("div", null, "toto"));
React.render(component, document.getElementById('root'));

La méthode utilisée pour créer un composant est la méthode “createElement“. Le premier paramètre est le nom de l’élément html à générer, le second est un JSON contenant les propriétés à appliquer au composant.

A partir du troisième argument, il s’agit de la liste des composants ‘enfants’. On peut y mettre du texte, d’autres composants ReactJs. Le code généré mettra les composants fils les uns à la suite des autres, dans l’ordre dans lequel ils sont passés en paramètre.

La méthode Render prend en paramètre le composant racine de notre arbre de composants, et l’élément du DOM à l’intérieur duquel on va afficher nos composants.

Le résultat généré lors de l’affichage de ce composant sur la page html sera le suivant :

Exemple ReactJs

code complet de la page

Petite remarque : la propriété utilisée pour définir la classe de l’élément html est la propriété ‘className’ et non la propriété ‘class’. Ce qu’il faut comprendre c’est que les propriétés qui sont passées au moment de la création d’un composant ne sont pas des propriétés html, mais bien des propriétés destinées à des composants React. C’est la responsabilité de la librairie Reactjs de générer correctement le html. La liste des propriétés est disponible ici

Les vues sont donc définies entièrement dans le code Javascript ?

Oui, …

L’API ReactJs permet de créer des composants plus ou moins complexes. Et le code de cette API n’est évidemment  accessible qu’en javascript.

Mais, …

On imagine bien que dans le cas d’une interface bien plus complexe, ce code risque de devenir beaucoup moins lisible. Par conséquent, les créateurs de ReactJs ont donc créé le JSX, qui va être le langage le plus utilisé lorsqu’on taraville avec ReactJs.

Il s’agit d’un langage très proche de Javascript, dans lequel on peut inclure un code proche du html pour définir les rendus des composants React.

Pour fonctionner, le code JSX est compilé en son équivalent Javascript. Et c’est ce code Javascript qui accède à l’API de ReactJs.

Il est possible d’écrire ce code JSX directement dans la page html (ce qui sera le cas des exemples de ce post). Pour ce faire, il faut, dans un premier temps, inclure le fichier “JSXTransformer.js“.

<script type="text/javascript" src="../chemin-vers-la-librairie/JSXTransformer.js"></script>

L’autre changement à apporter est d’écrire son code JSX dans une balise script “JSX” et non “Javascript”.

<script type="text/jsx">
 //ici le code JSX
</script>

Voici le code JSX correspondant à l’exemple de composant ReactJs précédent :

var component = <div className="div-class" >hello<div>toto</div></div>;
React.render(component, document.getElementById('root'));

code complet de la page

Petite remarque 1 : chaque code HTML inline sera remplacé par un code Javascript qui renverra un composant React (o un arbre de composants). Une fois de plus, les propriétés appliquées sont des propriétés React et non des propriétés HTML. Il ne s’agit donc pas réellement de code HTML.

Petite remarque 2 : L’usage du JSX directement dans la page HTML serait fortement déconseillé sur un environnement de Production, dû à de faibles performances. Il est possible de compiler à l’avance le code JSX et de référencer le Javascript ainsi généré dans la page HTLM. Ce qui permet d’améliorer les performances (pas de compilation/interprétation de JSX lors du chargement de la page), ou encore d’avoir un stratégie de minification/compilation du code Javascript généré.

Petite remarque 3 : Il est possible de voir le Javascript généré à partir d’un code JSX sur la page suivante : https://facebook.github.io/react/jsx-compiler.html

Et si on regardait ces composants de plus près ?

Voici un exemple de code JSX avec des composants un peu plus complexes :

var Node = React.createClass({
 render : function () {
   return (<div>
       {this.props.lioneltext}
     </div>);
 }
});

var Tree = React.createClass({
 render : function () {
   return (<div>
     root
     <Node lioneltext="premier noeud"/>
     <Node lioneltext="second noeud"/>
   </div>);
 }
});

React.render(<Tree />, document.getElementById('root'));

Et en voici le rendu :

Exemple ReactJs

code complet de la page

Dans cet exemple, nous avons défini, non pas des composants, mais des classes de composants.

La méthode utilisée pour créer une classe de composant, est la méthode “createClass“. Elle prend en paramètre un objet JSON. L’objet en question peut redéfinir des fonctions précises, qui seront appelées durant le cycle de vie du composant instancié à partir de cette classe (comment ils s’affichent, à quels moments leur état est invalidé, comment sont utilisées leurs propriétés spécifiques …).

Petite remarque : La liste des fonctions permettant de définir le comportement des composants d’une classe au cours de leur cycle de vie se trouve ici .

Dans notre exemple, nous créons 2 classes de composants, la classe “Tree” et la clesse “Node“. Dans les 2 cas, nous avons redéfini la fonction “render“. Il s’agit de la fonction appelée lorsque le composant doit s’afficher, elle doit retourner l’arbre de composants React à afficher, et c’est la seule fonction qu’il est obligatoire d’avoir défini dans l’objet à passer en paramètre de la fonction “createClass“.

La méthode “createClass” retourne donc une classe, et pour “instancier” un composant de cette classe en JSX, il suffit d’écrire une balise avec le nom de la classe.

Lorsque l’on écrit :

React.render(<Tree />, document.getElementById('root'));

On passe à la fonction render, le composant racine de notre arbre de composants qui ici est de type “Tree“, et l’élément du DOM à l’intérieur duquel il sera affiché.

Dans le cas de la classe “Node“, on définit une nouvelle propriété (la propriété “lioneltext“) :

<Node lioneltext="premier noeud"/>

Une fois cette propriété définie, on peut y accéder dans les fonctions de l’objet JSON en paramètre de “createClass” à l’intérieur de l’objet “this.props

render : function () {</pre>
  return (<div>
      {this.props.lioneltext}
    </div>);
}

Petite remarque : dans le cas où la propriété ne serait pas initialisée, si on essaie d’accéder à la propriété, elle sera en “undefined”. Il est possible de définir la valeur par défaut de l’objet “this.props” en définissant la fonction “getDefaultProps” (l’objet retourné contient les valeurs par défaut des propriétés).

Dans quel état sont nos composants ?

Jusqu’ici, nous nous sommes servis de ReactJs pour afficher des données (passées en propriétés) dans du contenu html construit grâce à l’API. Ce qui est à peu près ce que fait un moteur de template.

Cependant, ReactJs apporte une légère différence : les composants que nous créons peuvent avoir une gestion de leur état.

Pour faire simple, on peut voir l’état comme des propriétés privées qui peuvent être mises à jour (par exemple, par des interactions avec l’utilisateur), et changer l’affichage du composant.

Dans l’exemple, nous avons créé un composant personnalisé qui possède une zone d’input et une zone d’output. Ce composant affiche tout simplement le texte qui est rentré par l’utilisateur.

En voici le rendu :

Exemple ReactJs

code complet de la page

L’affichage de notre arbre de composants dépend donc de ce texte. Or, sa valeur ne peut pas être définie par une propriété, mais par d’autres interactions (avec l’utilisateur).

Ce texte va donc être “l’état” de notre composant.

Tout comme les propriétés du composant se trouvent dans “props“, l’état du composant est un objet JSON qui se trouve dans la propriété “state” (et se récupère donc via “this.state“).

La valeur initiale de l’état doit être retournée par la fonction “getInitialState“. Si cette fonction n’est par définie, la propriété “state” vaudra null.

Nous avons affecté des valeurs à 2 propriétés de l’input qui se trouvent dans notre composant.

La propriété “value” qui prend comme valeur une chaîne de caractères et qui permet de définir la valeur initiale de l’input. On y a affecté la valeur qui se trouve dans l’état.
Et la propriété “onChange” qui prend comme valeur une fonction prenant elle même un événement en paramètre. Ici, on y a affecté la fonction “updateWord“.

Le deuxième composant fils (“Hello“) ne fait qu’afficher le contenu de l’état.

Petite remarque : Dans la fonction updateWord, on met à jour l’état du composant. Pour se faire, on appelle la méthode “setState”, en lui passant en paramètre les modifications apportées (on n’est pas obligé de repasser l’ensemble du JSON qui constitue l’état mais uniquement un objet JSON contenant les propriétés à mettre à jour (on retrouve ici comportement proche de la fonction extend de jquery))

La méthode “setState” a pour effet d’invalider l’état du composant et donc de déclencher la mise à jour de son affichage.

Et… C’est tout ?

Pour l’instant oui …

Dans le prochain post sur ReactJs, on traitera de l’architecture Flux.

@lionel