React

Remi Forax

React ?

“ Front-end JavaScript library for building user interfaces based on UI components. React can be used as a base in the development of single-page, mobile, or server-rendered applications ... However, React is only concerned with state management and rendering that state to the DOM ...”

source: Wikipedia.org - React

JavaScript ?

“Bibliothèque cliente JavaScript pour créer des interfaces utilisateur à base de composants. React peut être utilisé comme base pour le développement d'applications Web à page unique, sur mobile ou générées coté serveur. React s'occupe uniquement de la gestion des états et de l'affichage ces états sur l'arbre DOM... ”

source: Wikipedia.org - React

Historique des versions

React 0.3.02013
React 15 (ex 0.15.0)2016
React 16.8 (Hooks)2019
React 192024
Open Source, maintenu par Meta (ex Facebook)

React ?

  • Des composants sous forme de fonctions (ou classes)
  • JSX : JavaScript Syntax eXtension (optionnel)
  • Deux points d'entrées : React et ReactDOM
  • Utilise un DOM virtuel mutable
  • Gère ses propres évènements

Exemple simple

createRoot(domNode) demande à React de gérer le nœud du DOM
render(element) affiche l'élément JSX en tant que fils de la racine


      <div id="react-simple"></div>
					

 

JavaScript Syntax eXtension

Permet d'écrire du HTML comme une expression JavaScript
On utilise '{' et '}' pour insérer une expression JavaScript dans le JSX

 

Nécessite un pré-processeur sur le code comme Babel ou esbuild

Traduction du JSX

Le JSX est transformé en appel à
React.createElement(type, props, ...children)

 

"props" veut dire properties !

esbuild

  • transforme les fichiers JSX (toto.jsx) en fichier JS (toto.js)
  • inclu (bundle) les libraries (react et react-dom)

Installation de esbuild en utilisant npm
npm install --save-exact --save-dev esbuild

Transpilation de JSX vers JS
./node_modules/.bin/esbuild toto.jsx --bundle --outfile=toto.js

L'option --watch permet de rebuilder automatiquement
L'option --serve=8080 --servedir="." lance un serveur web

Fonction comme composant

Les composants comme fonctions

On déclare un composant réutilisable avec une fonction

 

JSX fait la différence entre une fonction ou un tag HTML avec les majuscules !

Balise auto-fermante

Un slash après le nom d'un composant permet d'"auto-fermer" la balise

 

Cette notation vient du XHTML

Propriété des composants

Les attributs JSX sont transformés en Objet ("props") pris en paramètre de la fonction

 

Propriété (2)

Si une propriété n'est pas de type string, il faut passer la valeur entre '{' '}'

 

Style d'un composant

On utilise l'attribut DOM "className" plutôt que "class" pour spécifier la classe CSS


.tomato {
  color: tomato;
  background-color: blue;
}
					

Pour éviter la confusion avec le mot-clé "class"

Fragment

Il existe une syntaxe spéciale (<> et </>) pour encapsuler plusieurs éléments et les envoyer comme un seul élément

JSX conditionnel

JSX a une syntax spécial pour afficher de façon conditionnelle


    condition && <Whatever/>
				    

Le DOM virtuel

Virtual DOM ?

Le DOM virtuel est une copie du DOM qui utilise des objets JS plutôt que des objets C++

Lors d'un render(element), React regarde la différence entre l'arbre des élements et le DOM virtuel
Puis, React applique uniquement les changements sur le DOM !

Les listes

Une liste simple

Le code ci-dessous à un problème (cf la console)
Warning: Each child in a list should have a unique "key" prop.

React demande un attribut "key" pour tracker les items au niveau du DOM virtuel

L'attribut "key"

Doit être unique, permet de savoir quels éléments changent

Les attributs "key" doivent être stables !

State Hooks

Gestion des états / state hook

useState(initial) renvoie un tableau contenant la valeur actuelle (ou la valeur initiale si c'est la première fois) et une fonction qui met à jour la valeur et l'UI

React a sa propre gestion des évènements donc "onClick" au lieu de "onclick"

Destructuration des tableaux

Comme le résultat de useState() est un tableau, on peut extraire les valeurs en utilisant la destructuration des tableaux

Et aussi "onChange" au lieu de "onchange"

State Hook (2)

Chaque composant a son propre état

State hooks et DOM virtuel

Les states hooks sont stockés dans un tableau associé à chaque nœud du DOM virtuel

Tant qu'un nœud n'est pas supprimé l'état persiste

State Hook (3)

La fonction de mise à jour peut prendre une lambda en paramètre (oldValue => newValue)

State Hook (4)

On utilise les props si on veut configurer les composants avec des valeurs différentes.

Note: let {a,b} = c <=> let a = c.a; let b = c.b

Communication inter-composants

set... en tant que props

Le composant parent peut envoyer sa fonction de mise à jour (set...) en tant que props des composants enfants

Cette technique est appelé render props

Effect Hook

Effect Hook

useEffect(lambda, [val1, val2, etc]) execute la lambda après qu'une des valeurs ait changé

Si on ne spécifie pas de valeurs, on exécute l'effet à chaque fois !

Effect Hook (2)

useEffect(lambda, []), si on spécifie un tableau vide, l'effet est exécuté àprès le premier affichage

Appel asynchrone

Après un click

On met à jour en fonction du résultat de l'appel à fetch()

Lors du chargement

On utilise useEffect(function, [])

useEffect() ne permet pas les fonctions async, il faut passer setData en paramètre

Classe comme composant

(Ancienne façon de faire)

Les composants comme classe

Les "props" sont passés à la construction. L'appel à super() les stocke dans "this.props".
render() est appelée pour l'affichage.

États avec this.state / setState()

setState(object) prend un objet en paramètre, recopie tous les champs dans "this.state" puis change l'UI

si on change "this.state" au lieu de setState, l'UI est pas mise à jour !

Méthode de mutation (1/2)

On écrit la gestion des évènements dans une méthode pour que le code soit plus lisible

Méthode de mutation (2/2)

Ou on utilise "bind(this)"

setState et méthode d'update

Comme avec un state hook, setState peut prendre une méthode de mise à jour en paramètre

Attention, lorsque l'on retourne un objet dans une lambda, il faut des parenthèses !

Évènements et DOM virtuel

Cycle de vie

componentDidMount() est appelée lorsque l'objet du DOM correspondant est créé.
componentWillUnmount() est appelée lorsque l'objet du DOM disparait.

Cycle de vie et état

Chaque mise à jour du DOM appelle componentDidUpdate()
(sauf la première qui utilise componentDidMount)
useEffect = componentDidMount + componentDidUpdate