Edit 18/06/2018 : correction de fautes d’orthographes, de syntaxe, d’ambiguïté dans certaines formulations. Petit correctif suite aux évolutions de React après l’écriture de cette article

TL;DR

Il existe deux types de composant en React :

  • Composant fonctionnel : fonction prenant en paramètre un objet appelé props et retournant du JSX
  • Composant à état : Classe possédant obligatoirement une méthode render retournant du JSX, recevant des props et possédant un state représentant l’état interne du composant, modifiable en invoquant la fonction setState.

Aujourd’hui, nous allons nous intéresser à la base de toute application React, son alpha et son omega : le composant. Il en existe 2 types.

Le composant fonctionnel

Découvrons un composant fonctionnel dans sa forme la plus simple :

1
2
3
var HelloWorld = () => (
<p>Hello World</p>
);

C’est une fonction ayant la signature suivante void => JSX

Ce composant React est totalement statique en l’état, on ne peut pas modifier son état depuis l’extérieur. Pour régler cela, nous allons lui passer un objet en paramètre : un objet props. La signature de la fonction va donc changer pour devenir object => JSX.

On réécrit le composant HelloWorld de la façon suivante :

1
2
3
4
5
var HelloWorld = (props) => {(
//notre objet est de la forme { user : XXX }
let user = props.user;
return <p>Hello {user}</p>
)};

Notre composant a déjà bien évolué, que s’est-il passé ?

HelloWorld reçoit un objet en argument, on extrait son attribut user et, on l’insère dans notre JSX grâce à {}, ainsi, notre composant est devenu “dynamique” puisqu’il affiche un texte modifié en fonction de l’objet qu’il reçoit.

Ces props, le composant va les utiliser pour générer son UI, mais il ne peut pas les modifier.

Les props sont reçu du composant parent. Ce sont des éléments en “lecture seule” (on utilise également le terme “immuable”), ils ne sont pas modifiables depuis le composant mais affecte son rendu.

Pour rappel, le passage de props à notre composant se fait de la façon suivante en JSX: <HelloWorld user='Gaël' />

Si le composant que l’on vient d’écrire se nomme composant “fonctionnel”, c’est parce qu’il est créé en utilisant une fonction pure, une fonction dont le résultat ne dépend que des arguments reçus et rien d’autre.

Mais qu’en est-il si notre composant doit gérer un état interne pouvant influencer son rendu ?

Le composant à état (ou stateful)

Découvrons un composant stateful dans sa forme la plus simple :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class HelloWorld extends React.Component {
constructor(props) {
super(props);
this.state = {
happy : false
}
}
render() {
const user = this.props.user;
return (
<p>Hello {user}, I guess you are { !this.state.happy && "not" } happy today! </p> );
}
}

Un composant stateful est donc une classe JavaScript qui étend la classe Component de React. Pour le moment, nous n’allons pas nous attarder sur cet élément.

Comme toute classe, elle possède un constructeur (qui appelle le constructeur de la classe dont elle hérite via la méthode super.

La ligne suivant se révèle plus intéressante. On assigne en effet à this, notre objet courant (aka le composant React que l’on est en train de créer), un attribut que l’on nomme state. Dans le cadre de notre exemple, on l’initialise en créant une clé happy ayant la valeur false.

Ce state correspond à l’état interne de notre composant, contrairement au props venant du composant parent.
Ces deux éléments sont essentiels en React.

Ensuite, on trouve la méthode render, méthode INDISPENSABLE dans tout composant React stateful qui se respecte. C’est cette fonction qui sera appelée pour rendre le composant.

Pour faire un lien avec la première partie, on peut dire qu’un composant fonctionnel n’est qu’une fonction render.

Cette méthode render retourne quelque chose de très similaire au composant fonctionnel excepté que, cette fois, le this.state, l’état interne du composant ET le this.props peuvent impacter le JSX retourné.

En l’état, le composant à donc un état interne, seulement, rien ne peut le modifier. Le composant affichera donc toujours la même chose.

Pour changer cela, nous allons rajouter un bouton sur lequel cliquer déclenche le changement du state, faisant passer this.state.happy de true à false et inversement :

1
2
3
4
5
6
7
8
9
10
11
12
13
...
render() {
const user = this.props.user;
return (
<div>
<p>Hello {user}, I guess you are { !this.state.happy && "not" } happy today! </p>
<span>
<input type='button' value='Click me !'/>
</span>
</div>
);
}
}

Voilà pour la création du bouton, très similaire à ce que l’on ferait avec du HTML classique. Comment jouer avec le state maintenant ?
Pour rappel, on encapsule l’input et le p dans un div car un composant React ne doit retourner qu’un seul noeud DOM. Si ce n’est pas le cas, vous obtiendrez un erreur (on verra plus tard pourquoi).

edit: à partir de React 16, un composant peut retourner un tableau de composants. On lui préfère cependant le Fragment - un composant React qui n’apparaitra pas dans le DOM - et qui permet d’éviter d’encapsuler des componsants au même niveau dans l’arborescence par des div inutiles.

Pour commencer, le state ne se modifie qu’avec la méthode setState (on verra pourquoi dans un autre article), on passe toujours (toujours, toujours) par la méthode setState pour le modifier.

1
2
3
4
5
6
7
8
9
10
11
12
...
constructor(props) {
super(props);
this.state = {
happy : false
};
}
changerHumeur() {
this.setState({
happy : !this.state.happy
});
}

Maintenant, il faut brancher cette méthode au clique de notre bouton. Le JSX va nous être très utile puisqu’il nous permet de lier une méthode de la classe à un évènement DOM classique ( click, hover, submit, change, etc.) via une syntaxe particulière mais simple : la concaténation de “on” et du nom de l’event en camelCase*.

ex : onClick, onMouseOver, onSubmit, onChange, etc..

Ainsi, il suffira de modifier la méthode de rendering comme suit :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
render() {
let user = this.props.user;
return (
<div>
<p>
Hello {user}, I guess you are
{ !this.state.happy ? ' not ' : ' ' }
happy today!
</p>
<span>
<input type='button' value='Click me !' onClick={this.changerHumeur.bind(this)} />
</span>
</div>
)
};

Maintenant, cliquer sur le bouton appelle la méthode changerHumeur qui va changer le state via la méthode setState et donc mettre à jour le texte que le composant affiche ! Le composant répond maintenant aux interactions utilisateurs !

Pour résumé :

  • fonctionnel = fonction simple qui prend en argument un objet props et rend du contenu sous forme de JSX
  • stateful = composant “complexe” recevant des props et possédant son state interne interne pour générer son rendu.

Voilà pour la présentation des deux types de composants existants. Nous allons détailler dans un prochain article de quelle façon ces composants React se rattachent au DOM.

*La liste exhaustive est ici : https://facebook.github.io/react/docs/events.html#supported-events