React
Première partie
Technoweb L3 - Benjamin Becquet
Quelques jalons dans l'histoire des technologies du Web
1993 HTML : statique ou généré dynamiquement côté serveur
1995 JavaScript : ajout d'interactions côté client
1996 CSS : séparation structure / présentation
2004 AJAX (requêtes HTTP depuis JS) ➟ pages "dynamiques"
2006 jQuery : bibliothèque surcouche au DOM, manipulation des pages facilitée, plugins
2007 iPhone & Android : émergence d'un vrai web mobile
2010 Node.js + npm : JavaScript côté serveur, dépendances, explosion de l'écosystème
➟ maturité (ou du moins pertinence) de JS comme environnement de développement
2014 HTML5 : version modernisée, nouveaux éléments sémantiques
2015 ECMAScript 6 (ES6) : let/const , modules , classes, promesses, etc.
Et tout du long, évolution des navigateurs et enrichissement des standards.
Technoweb L3 - Benjamin Becquet 2
SPA : Simple Page Application
Modèle de développement apparu avec AJAX
UX similaire aux applications natives : pas de rechargement de page
Page HTML squelette unique + code applicatif entier en JavaScript côté client
Interrogation d'une API
Modification dynamique du DOM en JavaScript
Interception des navigations d'une url à l'autre (routing client)
Technoweb L3 - Benjamin Becquet 3
Technoweb L3 - Benjamin Becquet 4
Développement des SPA
➟ Développement se complefixiant très vite, notamment en terme de cohérence de l'interface
Frameworks JavaScript MVC (Backbone.js, Ember, AngularJS, etc.)
Architecture Model-View-Controller
Certains perçus comme trop dirigistes, peu performants, peu modulaires, etc.
Technoweb L3 - Benjamin Becquet 5
React
Introduit par Facebook en 2014
Dédié au développement de SPA
Présenté comme une bibliothèque, pas un framework
Se focalise sur la partie View de l'architecture MVC
Trés populaire, mais pas un standard du web
Principes :
faciliter l'écriture de composants réutilisables
garantir la cohérence de l'interface à chaque instant
modifier le DOM de manière performante et transparente
Documentation officielle (bien faite et entièrement traduite)
Technoweb L3 - Benjamin Becquet 6
Paradigmes de programmation
Programmation impérative Programmation déclarative
Description des étapes à suivre V.S.
Description du résultat voulu
Ex : "Quand le nom d'utilisateur change, le
Ex : "Dans le header et dans la liste des
mettre à jour dans le header et dans la liste messages, afficher le nom de
des messages" l'utilisateur courant"
en React, réalisé par ↓
Programmation réactive
Modification d'une source de données
(état) ➟ propagation aux éléments qui
en dépendent et mise-à-jour
Technoweb L3 - Benjamin Becquet 7
Exemple élémentaire
Document HTML Code Javascript
<!DOCTYPE html> import ReactDOM from 'react-dom';
<html>
<head> // composant
<script src="example.js"></script> function Hello(props) {
</head> return <h1>Hello {props.name} !</h1>
<body> }
<h1>Exemple React</h1>
<p>Éléments statiques</p>
// "accrochage" d'un composant React
<!-- élément prévu pour React --> // au DOM de la page
<div id="root"></div> ReactDOM.render(
</body> <Hello name="Alice" />,
</html> document.getElementById('root')
);
Une fois l'appel à ReactDOM.render(…) effectué, tout ce qui est à l'intérieur va être géré par React.
Technoweb L3 - Benjamin Becquet 8
Syntaxe JSX
Syntaxe proche du HTML, directement dans le code JavaScript, pour le render
les composants sont assimilés à des éléments HTML
les props sont assimilés à des attributs
Intérêts : rapidité d'écriture, encapsulation, rapprochement des concepts…
⚠️ Le JSX n'est pas du JavaScript valide ➟ repose sur une transpilation.
En développement JS moderne, on travaille souvent dans un environnement transpilé (Babel).
Ce qu'on écrit Transpilé en
const message = 'Hello, world!'; const message = 'Hello, world!';
const element = <h1 className="greeting"> const element = React.createElement(
{message} "h1",
</h1>; { className: "greeting" },
message
);
Technoweb L3 - Benjamin Becquet 9
Syntaxe JSX
On mélange la notation balises/attributs avec des expressions JavaScript entre accolades { … }
Variables, valeurs calculées, appels de fonctions
Structures de contrôles élémentaires (expressions booléennes et boucles map )
return (
<div className={isOpened ? 'opened' : 'closed'}>
<h3>Liste des utilisateurs</h3>
<ul>
{/* boucle */}
{props.users.map(user =>
<li key={user.id}>{formatUserName(user)}</li>
)}
</ul>
{/* affichage conditionnel */}
{errorMsg && <Error msg={errorMsg} />}
</div>
)
Technoweb L3 - Benjamin Becquet 10
Syntaxe JSX : quelques règles
false , null et undefined ne sont pas rendus dans le DOM
Toute balise doit être explicitement fermée ( <tag></tag> ou <tag /> )
La casse de la première lettre des balises est importante :
minuscule = balise HTML (ex : <h2>Introduction</h2> )
majuscule = composant React (ex : <UserName /> )
Certains noms d'attributs HTML sont renommés :
camelCase : onclick ➞ onClick , tabindex ➞ tabIndex , etc.
attributs en conflit avec des mots-clés JS : class ➞ className , for ➞ htmlFor , etc.
Les commentaires s'écrivent par blocs, aussi entre accolades {/* … */}
https://fr.reactjs.org/docs/introducing-jsx.html
Technoweb L3 - Benjamin Becquet 11
Deux syntaxes de déclaration de composant
Classe Fonction
Classe héritant de React.Component Fonction qui retourne du JSX
import { Component } from "react"; function MyComponent(props) {
return <h1>Hello {props.name} !</h1>;
class Hello extends Component { }
// seule méthode obligatoire
render() {
return <h1>Hello {this.props.name} !</h1>;
} const MyComponent = ({ name }) => {
// constructor, componentDidMount, etc. return <h1>Hello {name} !</h1>;
} }
Ancienne approche, orientée objet Approche moderne favorisée par React
Considérée comme legacy (obsolète) Plus proche du modèle conceptuel
Syntaxe plus légère
Contrôle plus fin des conditions de rendu
Technoweb L3 - Benjamin Becquet 12
Composants et props
// Un composant prend en argument un objet "props"
Une application React est constituée function User(props) {
// ce composant reçoit la prop 'name'
d'un arbre d'instances de composants return <li>Hello, {props.name}</li>;
}
Chaque composant peut rendre du // La syntaxe de destructuration d'objet
HTML et/ou d'autres composants // fait mieux apparaître les props en entrée
function App({ users }) {
Les données se propagent dans l'arbre return <ul>
{users.map(user =>
via les props (pour "properties"), <User name={user.name} key={user.id} />)}
</ul>;
de haut en bas }
Un composant est re-rendu const users = [
{ id: 1, name: 'Alice' },
automatiquement quand il reçoit de { id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
nouvelles valeurs de props ];
ReactDOM.render(
// passage de la prop 'users' en JSX
https://fr.reactjs.org/docs/components-and- <App users={users}/>,
document.getElementById('root')
props.html );
Technoweb L3 - Benjamin Becquet 13
Technoweb L3 - Benjamin Becquet 14
Props
On peut passer ce qu'on veut en props :
nombres, chaînes de caractères, booléens, objets, tableaux, etc.
fonctions callbacks (gestionnaires d'événements notamment, abordés plus loin)
du JSX, une instance de composant, un autre composant React
Une prop spéciale : children ➟ permet de passer sa valeur en contenu de la balise JSX.
const Details = ({ title, children }) => {
return <details>
<summary>{title}</summary>
{children}
</details>;
}
const App = () => {
return <Details title="Conditions d'utilisation">
<p>Article 1. : blabla</p>
<p>Article 2. : …</p>
</Details>
}
Technoweb L3 - Benjamin Becquet 15
Virtual DOM
Modifier le contenu d'une page dynamiquement nécessite de passer par l'API du DOM.
Par exemple : const myMessage = document.createElement('div');
myMessage.className = 'message';
myMessage.innerText = 'Lorem Ipsum';
const messageList = document.getElementById('messageList');
messageList.appendChild(myMessage);
React introduit une notion de "DOM virtuel" pour :
abstraire ces appels à travers la syntaxe JSX
optimiser les accès au DOM réel en appliquant des mises à jour minimales
https://fr.reactjs.org/docs/reconciliation.html
Technoweb L3 - Benjamin Becquet 16
State
Matérialise l'état interne d'un composant
Privé et encapsulé ➟ on passe par les props pour propager ce state aux enfants
Persistant entre deux rendus
Quand le state d'un composant change, le composant est automatiquement re-rendu
⚠️ Une des grandes questions d'une appli React est de savoir quel composant doit gérer quel state.
Deux composants qui partagent un état = descendants du même composant stateful
Un composant sans état (stateless) sera plus réutilisable (pas de "surprise")
https://fr.reactjs.org/docs/state-and-lifecycle.html
Technoweb L3 - Benjamin Becquet 17
Utilisation de useState : une horloge
import { useState, useEffect } from 'react';
const Clock = () => {
// useState() prend la valeur initiale et retourne
// [valeurCourante, fonctionDeModification]
const [date, setDate] = useState(new Date());
// mise à jour périodique
useEffect(() => {
const timerID = setInterval( // fonction JavaScript native
() => { setDate(new Date()); }, // callback
1000 // délai de 1 seconde
);
return () => { clearInterval(timerID); }
}, []);
return <div>Il est {date.toLocaleTimeString()}.</div>
}
ℹ️ useState et useEffect font parties des hooks, qu'on détaillera dans la seconde partie.
Technoweb L3 - Benjamin Becquet 18
Interactions utilisateurs
On attache des callbacks aux différents types d'événements via les attributs JSX dédiés :
onClick , onKeyPress , onFocus , onSubmit , … (version camelCase de ceux du HTML)
function EventExample() {
function handleClickButton() {
console.log('Bouton cliqué !')
}
function handleInputChange(event) {
console.log("Valeur de l'input : ", event.target.value);
}
return <>
<button type="button" onClick={handleClickButton}>Click!</button>
<input type="text" onChange={handleInputChange} />
</>;
}
Technoweb L3 - Benjamin Becquet 19
Interactivité = state + events
On crée des composants interactifs en modifiant leur state via des événements utilisateurs.
import { useState } from 'react';
function Clicker() {
const [nbClicks, setNbClicks] = useState(0);
const incrementNbClicks = () => {
setNbClicks(nbClicks + 1);
}
return <div>
<p>Nombre de clics : {nbClicks}</p>
<button type="button" onClick={incrementNbClicks}>Click!</button>
</div>;
}
Technoweb L3 - Benjamin Becquet 20
Passage de callbacks en props
➞ Permet la remontée d'informations aux parents en respectant le flux de propagation descendant.
// Composant stateless, prend le callback onChangeTheme en prop
function ThemeSwitch({ currentTheme, onChangeTheme }) {
return <div>
<button
disabled={currentTheme === 'dark'}
onClick={() => { onChangeTheme('dark'); }}>Dark</button>
<button
disabled={currentTheme === 'light'}
onClick={() => { onChangeTheme('light'); }}>Light</button>
</div>;
}
function App() {
const [theme, setTheme] = useState('light'); // L'état est maintenu ici
return <div>
<ThemeSwitch currentTheme={theme} onChangeTheme={setTheme} />
<Content theme={theme} />
</div>;
}
Technoweb L3 - Benjamin Becquet 21
Technoweb L3 - Benjamin Becquet 22
Résumé
Une application web React est constituée d'un arbre de composants
Les composants rendent des fragments de HTML, gérés dans le DOM par React
L'état de l'application est maintenu dans le state de certains composants
Les interactions utilisateur modifient ces states
Les changements de state sont propagés via les props de haut en bas dans l'arbre
Chaque changement de state/props entraîne le re-rendu des composants qui en dépendent
Bases pour concevoir une application web dynamique.
Technoweb L3 - Benjamin Becquet 23
Liens utiles
Site officiel React
React Developer Tools
Firefox
Chrome, Chromium, Edge
Create React App
Pour monter un environnement de développement avec un outillage pré-installé (utilisé en TME)
Technoweb L3 - Benjamin Becquet 24
Suite dans la deuxième partie :
Hooks et cycle de vie, connexion avec API, formulaires, React côté serveur.