À la découverte de React

React et JSX sont dans un bateau, personne ne tombe à l’eau !

En ces temps de Gutenberg on se doit de retourner aux basiques. Voici quelques tips.

La jungle des terminologies

Dépaysement total pour les dévs non natifs de la planète JavaScript ! Voyons certains termes que vous serez amenés à rencontrer tôt ou tard.

ES5, ES6, ES2015 et quoi d’autre ?

ES pour ECMAScript. JavaScript est une implémentation du standard ECMAScript.

ES5 et ES6 correspondent à des versions d’ECMAScript. À noter qu’on rencontre souvent le nom ES2015.

ES2015 c’est ES6 ! C’est une version du moteur publiée en juin 2015. 

Babel.js

Babel est un transcompilateur, un outil qui permet de convertir/compiler son code d’un langage de programmation à un autre. Ça peut servir à transformer de l’ES6 en ES5 par exemple (rétro-compat’ pour vieux navigateurs sur le retour XD ).

JSX

Non non non ceci n’est pas du HTML !  C’est une extension de JavaScript qui sert à décrire votre interface, comme un langage de template pour React mais en mode puissant.

Par exemple je passe par JSX pour les blocs Gutenberg, notamment Gutextra.

De toute manière en React de base, au lieu de faire en ES5 :

var el = wp.element.createElement;
function test() {
return el("div", { className: "myclass" }, el("p", {}, "Hey Sam !"));
}

on peut faire quelque chose comme :

function test() {
  return <div className="myclass"><p>Hey Sam !</p></div>;
}

À partir d’un certain niveau d’imbrication ça devient quand même plus pratique… mais encore une fois ce n’est pas du HTML, c’est une syntaxe qui permet de générer du HTML une fois le code compilé.

React, quelle est la logique ?

Je connais assez mal les frameworks et les librairies JavaScript mais je sais, du moins je lis partout, que React se démarque par son approche.

Inventé par les équipes de Facebook, React est certes une librairie JavaScript mais sa logique est fondée sur les composants. Avec un composant on peut générer des bouts de page (html) et ce, à chaque changement d’état.

Qu’est-ce qu’un composant ?

Un composant c’est une unité qui peut elle-même être constituée d’autres composants. On parle souvent de « composition » dans les applications créées avec React.

Le gain d’un tel fonctionnement est multiple. Le code est testable, maintenable facilement, et surtout réutilisable. 

Mais pourquoi React est dit plus rapide ?

Prenons le problème à l’inverse. Pourquoi sans React ce serait plus long, plus coûteux (en termes de perf) ?

Dans le navigateur, on a un truc qui s’appelle le DOM (Document Object Model), c’est une représentation sous formes d’objets de tous les éléments HTML ou XML de la page web.

Grosso modo dès qu’on modifie ce DOM, on génère systématiquement des opérations dans le navigateur qui entraînent tout un tas de recalculs notamment des styles CSS, des positionnements, etc.

N’oublions pas le côté historique des choses, le DOM a été inventé à une époque où les UI étaient bien moins complexes…

Partant de ce constat, React a créé un DOM virtuel dans lequel seules les opérations vraiment nécessaires sont déclenchées. Ce DOM virtuel est une copie du DOM (réel), dans lequel un algorithme de comparaison s’occupe d’identifier les éléments à modifier.

2 éléments anecdotiques ?

Fragment

Le « saviez-tu » ? Fragment qu’on voit à peu près partout et aussi dans Gutenberg vous permet de grouper des élements adjacents. En JSX, on ne peut pas juxtaposer des éléments comme ça, encore une fois ce n’est pas du HTML. Mais du coup ça peut devenir rapidement la foire aux div qui ne servent à rien. Fragment fixe ce problème et ne génère pas de markup pour éviter la « divite aiguë » :


import React, { Component, Fragment } from 'react'

class Welcomer extends Component {
  render () {
    return (
      <Fragment>
        <p>paragraphe 1</p>
        <p>paragraphe 2</p>
      </Fragment>
    )
  }
}

className

Avec React impossible d’utiliser l’attribut class comme avec du HTML. Le JSX n’étant pas du HTML c’est cohérent mais c’est surtout que le mot-clé class est réservé dans le langage :

class Welcomer extends Component {}

du coup on utilise className à la place :


import React, { Component, Fragment } from 'react'

class Welcomer extends Component {
  render () {
    return (
      <Fragment>
        <p className="paragraph">paragraphe 1</p>
        <p className="paragraph">paragraphe 2</p>
      </Fragment>
    )
  }
}

3 notions-clés à connaître

Props

Il s’agit d’un paramètre passé à un composant, l’équivalent de l’attribut pour une balise HTML. Sauf que props est un objet !

Les composants peuvent être vus comme des fonctions. On pourrait passer props en argument de notre fonction de tout à l’heure :

function Welcome(props) {
  return <div className="myclass"><p>Hi {props.name} !</p></div>;
}

Une autre manière d’écrire et que vous verrez souvent est :

class Welcome extends React.Component {
   render() {
     const {name} = this.props;
     return <div className="myclass"><p>Hi {name} !</p></div>;
   }
}

Ce que j’ai fait ici s’appelle destructurer les props, ça permet de récupérer et surtout utiliser plus facilement le name mais j’aurais pu tout aussi bien faire :

class Welcome extends React.Component {
   render() {
     return <div className="myclass"><p>Hi {this.props.name} !</p></div>;
   }
}

c’est le même code ! Le this c’est parce qu’on est dans une classe.

L’utilisation du composant qui correspond ressemble à ça :

<Welcome name="Sarah" />

State

State est une sorte de liant, de glue qui donne à React toute sa puissance.

Pour le modifier on utilise setState(). Chaque fois qu’on met à jour l’information cette fonction doit être appelée et un nouveau rendu (via le render()) est fait.

L’intérêt est de ne pas avoir à gérer des événements. Chaque fois qu’on va mettre à jour, tout sera re-rendu y compris tous les composants enfants.

Voyons ça avec un exemple tiré de la documentation officielle de React :

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

La date et l’heure doivent changer (c’est mieux pour une horloge) mais c’est une logique interne au composant Clock.

Quelle est la différence profonde ?

En d’autres termes, props ce sont les propriétés passées à un composant, l’équivalent d’arguments pour les fonctions, d’attributs pour le HTML.

state ne « vient pas de l’extérieur ». C’est vraiment propre au composant. C’est une logique interne.

Cette différence fondammentale fera qu’on parlera d’« immutable » pour props et de « mutable » pour state.

En gros, les props sont envoyées depuis les composants parents et on a pas la main dessus dans les composants enfants. Ils sont dit inchangeables (immutable).

Les states peuvent changer à tout moment et sont donc dits changeables (mutable).

Lifecycle

Au cours du cycle d’un composant on retrouve :

  • componentDidMount
  • componentDidUpdate

Il y en a d’autres mais je prends volontairement ceux-là pour mon exemple. Si je devais gérer en React la sauvegarde d’élements écrits dans un textarea je pourrais me tourner vers localStorage. Il faudrait agir à des moments précis sur mon composant. Pour se faire pas besoin de handler d’événement, c’est directement géré via React et le cycle de vie du composant :

  • localStorage.getItem() dans componentDidMount
  • localStorage.setItem() dans componentDidUpdate

import React, {Component, Fragment} from 'react';
import './App.css';

class App extends Component {
    state = {
        randomText: ''
    };

    componentDidMount() {
        const randomText = localStorage.getItem('randomText');

        if (randomText) {
            this.setState({randomText});
        } else {
            this.setState({randomText: 'blablabla'});
        }
    };

    componentDidUpdate() {
        const {randomText} = this.state;
        localStorage.setItem('randomText', randomText);
    };

    onChange = event => {
        const randomText = event.target.value;
        this.setState({randomText});
    };

    render() {
        return (
            <Fragment>
            <textarea
                onChange={this.onChange}
                value={this.state.randomText}
                />
                <p>
                    {this.state.randomText}
                </p>
            </Fragment>
        )
    }
}

export default App;

Pour tester le code j’utilise le wrapper de Facebook ça va plus vite : create app react.

Remarque importante : attention ici c’est vraiment pour l’exemple, si vous souhaitez faire ce genre de fonctionnalité, regardez du côté dangerouslysetinnerhtml. C’est pas très secure d’afficher ça directement.

Les bases JavaScript pour React

Un lien vaut mieux que 1000 mots supplémentaires (du moins dans ce billet) sur le sujet, donc voici un article (en) intéressant : https://www.robinwieruch.de/javascript-fundamentals-react-requirements/

Et en voilà un deuxième (en) qui vaut son pesant de cacahuètes aussi : https://www.taniarascia.com/getting-started-with-react/

Des outils pour travailler

De base, j’utilise :

Conclusion

React est puissant et pour celles et ceux qui souhaitent explorer Gutenberg, il vaut mieux passer par la case RTFM ( en français « lire la putain de doc » 🙂 ) avant de préférence. Il y a beaucoup de ressources disponibles de qualité et la documentation est claire.

Webographie

2 réactions pour À la découverte de React”

  1. belle mise en pied pour ceux qui souhaiteraient s’y mettre.
    Pas certains que les alias de gutenberg fassent gagner du temps lorsqu’on connait React. Mais c’est le point de vue d’un dev et non d’un themeur 🙂

    1. hello,
      il y a certaines questions concernant Gutenberg qui restent en suspens certes
      je ne suis pas tout à fait d’accord même de mon point de vue dév, je parle bien ici des composants genre mediaupload, iframe, embed, richtext, etc 😉

Les commentaires sont clos.