React

Introduction

React.js

React est une bibliothèque JavaScript développée par Facebook depuis 2013

Elle permet de :

  • Faciliter la création d'applications web monopages (Single Page Apps)
  • Mieux organiser et découper les éléments de l'interface utilisateur (UI) à l'aide de composants
  • Optimiser les performances de rendu des applications JavaScript

Angular, Vue et React

Comparaison

  • Framework complet
  • Google, 2016
  • Gros projets riches en fonctionnalités
  • Difficile à apprendre
  • Architecture MVC
  • Typescript + HTML
  • Data binding bi-directionnel
  • Grande communauté soutenue par de grandes entreprises
  • Framework complet
  • Evan You (ex Googler), 2014
  • Web app, App hybride
  • Petits et moyens projets
  • Facile à apprendre
  • Virtual DOM
  • JavaScript + HTML
  • Data binding uni-directionnel
  • Soutenu par la communauté open-source
  • Librairie pour créer des interfaces
  • Facebook, 2013
  • Complet (redux, router)
  • Web app, native ou hybride
  • Petits et moyens projets
  • Assez difficile à apprendre
  • Virtual DOM
  • JavaScript + JSX
  • Data binding uni-directionnel
  • Très grande communauté soutenue par de grandes entreprises

Component Angular


                                        import { Component, Input } from '@angular/core';
                
                                        @Component({
                                            selector: 'hello',
                                            template: `<h1>Hello {{name}} !</h1>`,
                                            styles: [`h1 { font-family: Lato; }`]
                                        })
                                        export class HelloComponent  {
                                            @Input() name: string;
                                        }                        
                                    

Component Vue


                                        <template>
                                            <h1>Hello {{name}} !</h1>
                                        </template>
                                        
                                        <script>
                                            export default {
                                                name : 'HelloComponent',
                                                props : {
                                                    name : String
                                                }
                                            }
                                        </script>
                                        
                                        <style scoped>
                                        </style>
                                    

Component React


                                        import React from 'react';
                                        import PropTypes from 'prop-types';
                
                                        export default function HelloWorld(props) {
                                            return (
                                                <h1>
                                                    Hello {props.name} !
                                                </h1>
                                            );
                                        }
                
                                        HelloWorld.propTypes = {
                                            name: PropTypes.string
                                        };
                                    

À retenir

Angular et Vue sont des frameworks

React est une librairie UI nécessitant d'autres librairies pour devenir un framework

Difficulté

Angular est le plus complexe, suivi par React et enfin Vue

Lequel est le plus performant ?

Bien maîtrisés, les trois solutions permettent d'obtenir des performances quasi-identiques

Qui choisir ?

Il faut choisir la solution en fonction du projet

Comparatifs

Google Trends

NPM Trends

JSX : Le langage de React

JSX est un langage développé par Facebook et qui permet de générer des éléments React avec une syntaxe rappelant HTML

Le développeur React écrit en JSX, lequel est compilé en JavaScript

La compilation se fait avec un transpiler,
comme Babel

Par exemple, on écrit ceci :


                                        const siteName = 'My portfolio';
                                        const navbar = (
                                            <nav>
                                                <a href="/home">{siteName}</a>
                                                <ul>
                                                    <li>Home</li>
                                                    <li>Projects</li>
                                                    <li>About</li>
                                                </ul>
                                            </nav>
                                        );
                                    

… qui sera compilé par Babel en ceci :


                                        const siteName = "My portfolio";
                                        const navbar = React.createElement(
                                            "nav", null,
                                            React.createElement( "a", { href: "/home" }, siteName ),
                                            React.createElement(
                                                "ul", null,
                                                React.createElement("li", null, "Home"),
                                                React.createElement("li", null, "Projects"),
                                                React.createElement("li", null, "About")
                                            )
                                        );
                                    

Le JSX permet au développeur de facilement écrire l'interface avec un langage proche du HTML

Nous verrons plus en détail les particularités de ce langage plus loin dans le cours …

Démarrer un projet React

Démarrer un projet React en écrivant à la main toute la configuration nécessaire à la compilation est fastidieux

Au début, on utilisait un package NPM appelé
create-react-app

Ce programme est toutefois assez lent à l'exécution.

Depuis quelques temps maintenant, c'est le package ViteJS qui est conseillé
vite

Ce programme va générer un projet React
pré-configuré et prêt-à-l'emploi

Créer un projet React du nom de "myapp" :


              npm create vite@latest myapp -- --template react
            

Cela peut prendre un peu de temps …


                cd myapp
                npm install
                npm run dev
            

Cela va lancer un serveur de développement, accessible dans le navigateur à l'adresse http://localhost:5173

Le projet généré aura la structure suivante :

On travaillera majoritairement dans les dossiers public/ et src/

Le fichier principal src/main.jsx correspond
au point de démarrage


              import React from 'react'
              import ReactDOM from 'react-dom/client'
              import App from './App'
              import './index.css'

              ReactDOM.createRoot(document.getElementById('root')).render(
                <React.StrictMode>
                  <App />
                </React.StrictMode>,
              )
            

Lors de la compilation, c'est ce fichier qui sera lu en premier

Étudions ce fichier par petits morçeaux …


            import React from 'react'
            import ReactDOM from 'react-dom/client'
          
  • React est la bibliothèque
  • ReactDOM gère le rendu dans la page web

            import App from './App'
            import './index.css'
          
  • Importe le composant se trouvant dans App.jsx
    ( préciser l'extension ".jsx" n'est pas nécessaire)
  • Charge le CSS principal de l'application (qui sera compilé par babel)

            ReactDOM.createRoot(document.getElementById('root')).render(
              <React.StrictMode>
                <App />
              </React.StrictMode>,
            )
          
  • Indique à ReactDOM que le composant <App/> sera rendu dans l'élément <div id="root"></div> de public/index.html
  • <React.StrictMode> indique que l'application utilise le mode strict de React (Plus d'infos ici : fr.reactjs.org/docs/strict-mode.html)
  • Appeler un composant React revient à l'écrire comme une balise HTML

Le composant <App/> est le composant principal qui sera rendu dans la page web par React

Un composant React est une fonction rangée dans un fichier .jsx et qui porte généralement le même nom

Ce fichier doit exporter par défaut la fonction définissant le composant

src/App.jsx


            import { useState } from 'react'
            import reactLogo from './assets/react.svg'
            import './App.css'
            
            function App() {
              const [count, setCount] = useState(0)
            
              return (
                <div className="App">
                  <div>
                    <a href="https://vitejs.dev" target="_blank">
                      <img src="/vite.svg" className="logo" alt="Vite logo" />
                    </a>
                    <a href="https://reactjs.org" target="_blank">
                      <img src={reactLogo} className="logo react" alt="React logo" />
                    </a>
                  </div>
                  <h1>Vite + React</h1>
                  <div className="card">
                    <button onClick={() => setCount((count) => count + 1)}>
                      count is {count}
                    </button>
                    <p>
                      Edit <code>src/App.jsx</code> and save to test HMR
                    </p>
                  </div>
                  <p className="read-the-docs">
                    Click on the Vite and React logos to learn more
                  </p>
                </div>
              )
            }
            
            export default App
          

http://localhost:5173

JSX

La syntaxe JSX

Remplacez le contenu de App.jsx par ceci :


            import React from 'react';
            import './App.css';
            
            function App() {
              const monTitre = 'Hello React!';
            
              return (
                <div className="App">
                  <h1>{monTitre}</h1>
                </div>
              );
            }
            
            export default App;                        
          

Supprimez également les fichiers assets/react.svg, public/vite.svget les styles présents dans App.css

L'affichage de variables en JSX se fait
entre accolades { }


                                        const monTitre = 'Hello React!';
                                        return (
                                            <h1>{monTitre}</h1>
                                        );
                                    

On appelle cela une expression

On peut écrire du "Vanilla JavaScript" dans les expressions :


                                        const monTitre = 'Hello React!';
                                        return (
                                            <h1>{monTitre.toUpperCase()}</h1>
                                        );
                                    

Il s'agit bien de JS standard. On peut utiliser tout ce qu'on connaît du langage 👍

Les expressions peuvent être utilisées
partout dans le JSX


                                        const cardStyle = { flex : 'initial' };
                                        const photoLink = './path/to/image.jpg';
                                        const title     = 'One Life';
                                        const artist    = 'Ed Sheeran';
                                        const album     = 'Yesterday OST';
                                        const musicFile = './path/to/music.mp3';
                
                                        return (
                                            <div className="card w-50" style={cardStyle}>
                                                <img className="align-self-center mr-2 w-25" src={photoLink} alt=""/>
                                                <h5 className="card-title">{title}</h5>
                                                <h6 className="card-subtitle mb-2 text-muted">{artist} / {album}</h6>
                                                <audio src={musicFile} className="w-100" controls></audio><br/>
                                            </div>
                                        );
                                    


Particularités en JSX

Les éléments doivent tous êtres refermés
par un slash /


                                        (<div>
                                            <br/>
                                            <img src="…" alt="" />
                                            <hr/>
                                            …
                                        </div>)
                                    

On applique la syntaxe du langage XML et non du HTML 5

Certains attributs HTML comme class ou for doivent être remplacés par des équivalents


                                        (<label htmlFor="searchText" className="col-form-label">
                                            Trier par :
                                        </label>)
                                    

Cela est dû au fait que "class" et "for" sont des mots-clés réservés en JavaScript

Un composant ne doit retourner qu'un seul noeud racine


                                        function App() {
                                            const monTitre = 'Hello React!';
                                          
                                            return (
                                                <div>
                                                    <h1>{monTitre}</h1>
                                                    <p>Bienvenue sur ma page web faite avec React</p>
                                                </div>
                                            );
                                        }
                                    

Si on ne souhaite pas générer de <div> superflue, on peut utiliser les React Fragments


                                        function App() {
                                            const monTitre = 'Hello React!';
                                          
                                            return (
                                                <>
                                                    <h1>{monTitre}</h1>
                                                    <p>Bienvenue sur ma page web faite avec React</p>
                                                </>
                                            );
                                        }
                                    
React

« React : Bien démarrer »
https://fr.reactjs.org/docs/getting-started.html

React

Components

React.js

Principe de base

Le principe des composants est fondé sur la notion d’autonomie et de réutilisabilité. Ils permettent ainsi de considérer chaque élément de manière isolée.

Les éléments HTML sont de parfaits exemples de composants.


                        <input type="text" maxlength="10" placeholder="Votre texte ici…" />
                    
  • La balise <input> en HTML permet de créer une zone de texte intéractive.
  • Elle réagit aux frappes de clavier et affiche les caractères saisis à l’intérieur.
  • Elle peut être paramétrée via les attributs (type, maxlength, placeholder, value, min, max, …)

                        <video width="400" height="225" controls>
                            <source src="bigbuckbunny.webm" type="video/webm">
                        </video>
                    
  • La balise <video> offre plus de fonctionnalités, notamment via l’utilisation des différentes balises <source> internes.
  • Elle dispose aussi de son propre style visuel.

Un composant est donc un élément qui embarque :


… des données

… des styles

… des comportements

Tout comme les balises HTML standards, les composants permettent de mieux structurer les applications web en les découpant en plusieurs morceaux ré-assemblables, autonomes et fonctionnels.

Composants en React

Au sens de React, les composants sont comme des fonctions JavaScript.
Ils acceptent des entrées (appelées « props ») et renvoient des éléments décrivant ce qui doit s'afficher à l'écran.

Function components

Le moyen le plus simple de définir un composant React consiste à écrire une fonction JavaScript :


                        function Jedi (props) {
                            const title = props.isMaster ? 'Maître' : 'jeune Padawan';
                            return <h1>Bienvenue {title} {props.name}</h1>
                        }
                    

Cette fonction est un composant React car elle accepte un seul argument "props" qui est un objet contenant des données, et renvoie un élément JSX à afficher.

Cela s'appelle une fonction composant

Class components

Il est également possible d'utiliser les classes ES2015 pour définir un composant :


                        class Welcome extends React.Component {
                            render() {
                                const title = this.props.isMaster ? 'Maître' : 'jeune Padawan';
                                return <h1>Bienvenue {title} {this.props.name}</h1>
                            }
                        }
                    

Les deux façons de faire sont équivalentes et disposent de fonctionnalités supplémentaires afin de les rendre intéractifs.

Nous étudierons ici les function components, plus réçents et plus succints à écrire.

Utilisation d'un composant

Un composant s'écrit à la manière d'une balise HTML :


                        // Jedi.jsx
                        export default function Jedi (props) {
                            const title = props.isMaster ? 'Maître' : 'jeune Padawan';
                            return <h1>Bienvenue {title} {props.name}</h1>
                        }
                    

                        // App.jsx
                        import Jedi from './Jedi.jsx';

                        export default function App() {
                            return (
                                <main>
                                    <Jedi name="Obi-Wan Kenobi" isMaster={true} />
                                </main>
                            )
                        }
                    

React considère les composants commençant par des minuscules comme des balises DOM.

Par exemple, <div> représente une balise HTML, mais <Welcome /> représente un composant et exige qu'il soit référencé dans la portée courante (= importé).

Composition

Les composants permettent de faire de la composition et d'être réutilisés autant de fois que souhaité :


                        <main class="app">
                            <Jedi name="Obi-Wan Kenobi" isMaster={true} />
                            <Jedi name="Qui-Gon Jinn" isMaster={true} />
                            <Jedi name="Anakin Skywalker" isMaster={false} />
                        </main>
                    

Les props

Les props sont aux composants ce que les attributs sont aux balises HTML.


                            <input type="checkbox" checked="checked">
                        
« type » et « checked » sont des attributs de la balise <input>

                            <Jedi name="Obi-Wan Kenobi" isMaster={true} />
                        
« name » et « isMaster » sont des props du composant <Jedi>

Dans la définition du composant, elles se récupèrent dans le seul paramètre « props » de la fonction

(ou dans this.props pour les class components)


                        function Jedi (props) {
                            const name     = props.name;
                            const isMaster = props.isMaster;
                            
                            …
                        }
                    

À noter qu'on peut utiliser la syntaxe de décomposition ES2015 sur l'objet « props »


                        function Jedi ({name, isMaster}) {
                            …
                        }
                    

Lecture seule

Les props sont toujours en lecture seule ! Il n'est pas possible de les modifier.


                        function Jedi (props) {
                            props.name = props.name.toUpperCase(); ❌
                            …
                        }
                    

Cela part du principe simple que les fonctions React sont tout le temps des fonctions pures

Pour faire évoluer l'état d'un composant, on ne peut donc pas faire muter les props.

On utilisera alors plutôt le concept d'état local, qui sera présenté dans le prochain cours…

React

« React : Components et props »
https://fr.reactjs.org/docs/components-and-props.html

React

Événements

React.js

La gestion des événements en React se fait de la même façon qu'en HTML classique, malgré quelques différences de syntaxe (et de fonctionnement interne)

En HTML classique, on peut écrire :


                            <button onclick="startApp()">
                                Démarrer l'application
                            </button>
                        

En React, on écrit plutôt :


                            <button onClick={startApp}>
                                Démarrer l'application
                            </button>
                        

Généralement, il n'est pas conseillé d'employer la méthode du HTML classique pour des raisons de séparation entre la structure et la présentation du code.

De plus, référencer un gestionnaire d'événement via un attribut revient à rendre disponible la fonction JS dans l'espace global, et/ou potentiellement limiter les performances si le HTML venait à changer dynamiquement.


… en gros, ne faites jamais ceci en HTML classique :


                        <button onclick="startApp()">
                            Démarrer l'application
                        </button>
                    

Préférez plutôt l'utilisation de addEventListener en JS pur.

En React cependant, même si la syntaxe recommandée ressemble à celle déconseillée en HTML, le fonctionnement interne n'est pas du tout le même.

React gère intelligemment et de façon optimisée les gestionnaires d'événements, leur propagation et leur remontée (bubbling).

Seul le côté pratique de la syntaxe a été conservé.


En React, on écrit donc ceci :


                        <button onClick={startApp}>
                            Démarrer l'application
                        </button>
                    

Remarquez que le nom de l'événement s'écrit en camelCase, et que la valeur de la prop référence une fonction, sans l'exécuter avec les parenthèses ()

Les fonctions référencées se comportent comme des fonctions d'événement JS classique, aux différences suivantes :

  • Le paramètre d'événement event est un événement synthétique créé par React.
  • Il n'est pas possible de renvoyer false pour stopper le comportement par défaut de la fonction. On utilise plutôt event.preventDefault() pour cela.
  • Il n'est possible d'utiliser this pour désigner l'élément ayant déclanché l'événement. On utilise plutôt event.target pour cela.

                        export default function App () {
                            function onFruitClick(event) {
                                event.preventDefault();
                                const fruit = event.target.textContent;
                                console.log(`Vous avez cliqué sur ${fruit}`);
                            }

                            return (
                                <ul>
                                    <li onClick={onFruitClick}>Pêche</li>
                                    <li onClick={onFruitClick}>Banane</li>
                                    <li onClick={onFruitClick}>Leetchi</li>
                                </ul>
                            );
                        }
                    
Tester ce code

Tous les événements JavaScript peuvent s'écouter avec cette syntaxe :


                        <form onSubmit={ … }>
                        <div onMouseMove={ … }>
                        <input onKeyDown={ … }>
                        <select onBlur={ … } onFocus={ … }>
                        <video onPlay={ … }>
                    

Passer des arguments

On a parfois besoin de vouloir passer un argument supplémentaire à un gestionnaire d'événement.

Dans ce cas, on utilise une fonction fléchée :


                        <button onClick={(event) => deleteTasks(task, event)}>
                            Supprimer la tâche
                        </button>
                    
React

« React : Gérer les événements »
https://fr.reactjs.org/docs/handling-events.html

React

Les Hooks

React.js

Les hooks sont arrivés dans la
version 16.8.0 de React

Ils permettent d'attacher un comportement réutilisable à un composant de type function

Avant cela, on utilisait des solutions telles que les props de rendu ou les composants d'ordre supérieur

Mais cette approche nécessitait la restructuration des composants, et rendait le code plus lourd et difficile à maintenir

React a besoin d’une meilleure primitive pour la réutilisation des logiques à état.
Les Hooks vous permettent de réutiliser de la logique à état sans modifier la hiérarchie de vos composants.

fr.reactjs.org/docs/hooks-intro.html#motivation

Alors, qu'est ce qu'un hook ?

Concrètement, ce sont des fonctions qui permettent de « se brancher » sur la gestion d’état local et le cycle de vie de React

Ils s'appellent directement à la racine du composant, et ne fonctionnent que pour les composants de type function

Les hooks prédéfinis

React offre plusieurs Hooks de base :

  • 📌 Hook d’état   useState()
  • ➡ Hook de référence   useRef()
  • ⚡️ Hook d’effet   useEffect()
  • 📓 Hook de contexte   useContext()

Le hook d'état
📌 useState()

useState permet de déclarer des variables d'état dynamiques

L'avantage d'une telle variable est que React peut surveiller son changement de valeur, et mettre à jour la vue en conséquence

Pour utiliser ce hook, il faut d'abord l'importer :


                            import React, {useState} from 'react';
                        

Puis on l'utilise dans la fonction de composant :


                            const [prenom, setPrenom] = useState('');
                        

useState accepte un argument définissant la valeur par défaut de la variable

Elle renvoie un tableau composé de 2 valeurs :
la variable elle-même et une fonction permettant de la mettre à jour

Par convention, la méthode de modification commence par « set »

Exemple complet :


                            import React, {useState} from 'react';
    
                            export default function Hello() {
                                const [prenom, setPrenom] = useState('');
    
                                function onTextChange(event) {
                                    setPrenom(event.target.value);
                                }
    
                                return (
                                    <div>
                                        <h1>Hello {prenom} !</h1>
                                        <input type="text" onChange={onTextChange} />
                                    </div>
                                );
                            }
                        

Tester le code

La méthode de modification doit systématiquement définir un nouvel objet

Il faut donc faire attention lorsqu'on modifie une variable d'état contenant un objet littéral {} ou un tableau [] JavaScript à ne pas faire muter l'objet, mais bien le remplacer !

Pour les Arrays :

❌ Ne pas faire :


                                // Ajout d'un nouvel article
                                articles.push("Fraises");
                                setArticle(articles);
                            

✅ Faire :


                                // Ajout d'un nouvel article
                                setArticle([...articles, "Fraises"]);
                            

Pour les Objects :

❌ Ne pas faire :


                                // Masque un élément
                                style.display = 'none';
                                setStyle(style);
                            

✅ Faire :


                                // Masque un élément
                                setStyle({
                                    ...style,
                                    display: 'none'
                                });
                            

Documentation

https://fr.reactjs.org/docs/hooks-state.html

Le hook de référence
useRef()

Le hook de référence renvoie un objet « ref » modifiable dont la propriété current est initialisée avec l'argument fourni.


            import React, { useRef } from 'react';
            
            export default function Hello() {
              const myref = useRef(0);

              return <>{myref.current}</>;
            }
          

On s'en sert quand on veut conserver une valeur entre différents re-renders.


            import React, { useRef } from 'react';
            
            export default function Hello() {
              const rendersCounter = useRef(0);

              rendersCounter.current++;

              return <p>Composant rendu {rendersCounter.current} fois!</p>;
            }
          

On peut aussi l'utiliser pour accéder directement à un élément du DOM grâce à la prop ref={}


            import React, { useRef } from 'react';

            export default function Hello() {
              const inputEl = useRef(null);

              function onButtonClick() {
                // `current` fait référence au champ <input> ci-dessous
                inputEl.current.focus();
              };

              return (
                <>
                  <input type="text" ref={inputEl} />
                  <button onClick={onButtonClick}>Donner le focus</button>
                </>
              );
            }
          

En gros, useRef est comme une « boîte » qui pourrait contenir une valeur modifiable dans sa propriété .current.

Documentation

https://fr.reactjs.org/docs/hooks-reference.html#useref

Le hook d’effet
⚡️ useEffect()

Le hook d'effet permet l'exécution d'effets de bord dans les fonctions composants

Concrètement, il permet de réagir à des actions comme :

  • Le démarrage du composant
  • Le changement d'une (ou plusieurs) valeurs du state
  • La suppression du composant

Il est très pratique lorsqu'on a besoin de faire un appel vers une API quand le composant démarre, ou pour déclencher des actions suite à une modification du state

Pour utiliser ce Hook, on l'importe depuis React :


              import React, { useEffect } from 'react';
          

Puis on le renseigne dans le composant de fonction:


              function Hello() {
                useEffect(() => {
                  // Le code d'effet ici …
                });
              }
          

Exemple complet :


                            import React, {useState, useEffect} from 'react';
    
                            export default function App () {
                                const [counter, setCounter] = useState(0);
                                
                                useEffect(() => {
                                    // Met à jour le titre du document
                                    document.title = `Vous avez cliqué ${counter} fois !`;
                                });
                                
                                function increment() {
                                    setCounter(counter + 1);
                                }
                                
                                return (
                                    <button onClick={increment}>{counter}</button>
                                );
                            }
                        

Par défaut, useEffect va s'exécuter à chaque fois que le composant est mis à jour, ce qui n'est pas toujours le comportement souhaité

Pour cela, on peut préciser comme 2ème paramètre un Array [] vide :


                            function Hello() {
                                useEffect(() => {
                                    // Le code d'effet ici …
                                }, []);
                            }
                        

Ce code d'effet ne s'exécutera qu'une seule fois au démarrage du composant
(ce qui est pratique pour initialiser un appel API par exemple)

⚠️ Attention !
Depuis React 18, le hook d'effet au démarrage va s'exécuter 2 fois (en mode Strict).
Plus d'infos ici : reactjs.org/docs/strict-mode.html#ensuring-reusable-state

Si on doit faire un API call au chargement d'un composant, il faut alors s'assurer de ne le faire qu'une fois :


              import React, { useEffect, useRef } from 'react';

              function UserPage({ userId }) {
                const effectCalled = useRef(false);

                useEffect(() => {
                  async function fetchUser() {
                    fetch(`/api/users/${userId}`).then(…);
                  }

                  if (!effectCalled.current) {
                    fetchUser();
                    effectCalled.current = true;
                  }
                }, []);
              }
            

On peut aussi renseigner une ou plusieurs variables d'état dans l'Array, pour n'effectuer une action que si ces variables là sont modifiées :


                            function Hello() {
                                useEffect(() => {
                                    // Le code d'effet ici …
                                }, [counter, prenom]);
                            }
                        

Ce code d'effet ne s'exécutera que lorsque les variables counter ou prenom seront modifiées

Le hook d'effet peut parfois avoir besoin d'être « nettoyé » lors de la suppression du composant

Par exemple, si au démarrage du composant, on écrit un gestionnaire d'événement avec addEventListener, il faut également écrire le removeEventListener correspondant, et ce pour des raisons de performance

Ainsi, chaque Hook d'effet peut renvoyer une fonction qui sera appelée par React dès qu'un nettoyage s'impose :


                            function Hello() {
                                useEffect(() => {
                                    // Attache un gestionnaire d'événement
                                    document.addEventListener('mousemove', onMouseMoving);
    
                                    return () => {
                                        // Détache le gestionnaire d'événement créé au démarrage
                                        document.removeEventListener('mousemove', onMouseMoving);
                                    };
                                }, []);
                            }
                        

https://fr.reactjs.org/docs/hooks-effect.html#effects-with-cleanup

Documentation

https://fr.reactjs.org/docs/hooks-effect.html

Le hook de contexte
📓 useContext()

Le hook de contexte résoud une problématique simple, à savoir la transmission de valeur d'un composant à l'autre

D'ordinaire, lorsqu'on souhaite transmettre une valeur d'un composant parent à un composant enfant, on utilise les props :


                            const todos = [ {title:"Acheter du pain"} , {title:"Nourrir le chat"} ];
    
                            function App() {
                                return (
                                    <Todolist todos={todos} />
                                );
                            }
    
                            function Todolist(props) {
                                return (
                                    <ul>
                                        {props.todos.map((todo, index) => (
                                            <li key={index}>{todo.title}</li>
                                        ))}
                                    </ul>
                                );
                            }
                        

Transmettre des valeurs via les props est une bonne méthode quand les composants sont proches …

… mais parfois, les composants sont éloignés …

Le passage via les props va déboucher sur l’anti pattern de « forage des props »
( props drilling )

Pour éviter cela, nous avons à notre disposition
le Hook Context

Le Contexte permet de mettre à disposition des données globales via un Provider.

Tout composant ayant besoins de ces données pourra y accéder via un Consumer.

On utilisera le Contexte uniquement quand on ne peut faire autrement, car il rend la réutilisation des composants plus difficile.

Pour créer un Contexte, il faut définir un module qui met à disposition les données via un Provider et un Consumer

On initialise un nouveau contexte avec la méthode createContext() de React

UserContext.js


                            import React, {createContext} from 'react';
    
                            const UserContext = createContext({ name: "Zuckerberg", age: 35 });
    
                            export const UserProvider = UserContext.Provider;
                            export const UserConsumer = UserContext.Consumer;
                            export default UserContext;
                        

Ensuite, pour que le contexte soit accessible, il doit faire parti des composants parents de ceux qui vont y accéder

Le Provider met à disposition les données

App.js


                            import React from 'react';
                            import Hello from './Hello';
                            import { UserProvider } from './UserContext';
    
                            function App() {
                                const user = { name: 'Wozniak', age: 69 };
                               
                                return (
                                    <UserProvider value={user}>
                                        <Hello />
                                    </UserProvider>
                                )
                            }
                        

La prop "value" du Provider va mettre à disposition l'objet user
à tous les enfants de ce Provider

Enfin, lorsqu'on souhaite dans un composant enfant accéder au contexte, on utilisera le hook useContext()

Hello.js


                            import React, {useContext} from 'react';
                            import UserContext from './UserContext';
    
                            function HomePage() {
                                const user = useContext(UserContext);
    
                                return (
                                    <h3>{user.name}</h3>    // ✅
                                    <span>{user.age}</span> // ✅
                                );
                            }
                        

À retenir

On créé le contexte avec React.createContext()

On exporte le Provider et le Consumer du contexte

On enveloppe les composants avec le Provider

On utilise le hook useContext() pour accéder aux données

Documentation

https://fr.reactjs.org/docs/context.html

💡

Hooks complémentaires de React :

  • useReducer
  • useCallback
  • useMemo
  • useImperativeHandle
  • useLayoutEffect
  • useDebugValue

https://fr.reactjs.org/docs/hooks-reference.html#additional-hooks

React

« React : Introduction aux hooks »
https://fr.reactjs.org/docs/hooks-intro.html