Ajouter de lâinteractivitĂ©
Certaines choses Ă lâĂ©cran se mettent Ă jour en rĂ©ponse aux actions de lâutilisateur. Par exemple, en cliquant sur une galerie dâimages, lâimage active change. En React, les donnĂ©es qui changent au fil du temps sont appelĂ©es Ă©tat. Vous pouvez ajouter un Ă©tat Ă nâimporte quel composant et le mettre Ă jour quand nĂ©cessaire. Dans ce chapitre, vous apprendrez Ă Ă©crire des composants qui gĂšrent des interactions, mettent Ă jour leur Ă©tat et ajustent leur affichage au fil du temps.
Dans ce chapitre
- Comment gĂ©rer les Ă©vĂ©nements initiĂ©s par lâutilisateur
- Comment faire en sorte que les composants « se souviennent » des informations grùce aux états
- Comment React met Ă jour lâinterface utilisateur (UI) en deux phases
- Pourquoi lâĂ©tat ne se met pas Ă jour immĂ©diatement aprĂšs sa modification
- Comment cumuler plusieurs mises Ă jour dâun mĂȘme Ă©tat
- Comment mettre Ă jour un objet dans lâĂ©tat
- Comment mettre Ă jour un tableau dans lâĂ©tat
Réagir aux événements
React vous permet dâajouter des gestionnaires dâĂ©vĂ©nements Ă votre JSX. Les gestionnaires dâĂ©vĂ©nements sont vos propres fonctions qui seront dĂ©clenchĂ©es en rĂ©ponse aux interactions de lâutilisateur telles que des clics, survols, activations de champs de saisie de formulaires, etc.
Les composants natifs tels que <button>
ne prennent en charge que les événements natifs du navigateur tels que onClick
. Cependant, vous pouvez Ă©galement crĂ©er vos propres composants et donner Ă leurs props de gestionnaires dâĂ©vĂ©nements des noms spĂ©cifiques Ă lâapplication, selon vos besoins.
export default function App() { return ( <Toolbar onPlayMovie={() => alert('Lecture en cours !')} onUploadImage={() => alert('Téléversement en cours !')} /> ); } function Toolbar({ onPlayMovie, onUploadImage }) { return ( <div> <Button onClick={onPlayMovie}> Voir le film </Button> <Button onClick={onUploadImage}> Téléverser une image </Button> </div> ); } function Button({ onClick, children }) { return ( <button onClick={onClick}> {children} </button> ); }
PrĂȘt·e Ă en apprendre davantage ?
Lisez RĂ©agir aux Ă©vĂ©nements pour apprendre comment ajouter des gestionnaires dâĂ©vĂ©nements.
En savoir plusLâĂ©tat : la mĂ©moire dâun composant
Les composants ont souvent besoin de modifier ce qui est affichĂ© Ă lâĂ©cran en rĂ©ponse Ă une interaction. Par exemple, saisir du texte dans un formulaire devrait mettre Ă jour le champ de saisie, cliquer sur « suivant » dans un carrousel dâimages devrait changer lâimage affichĂ©e, cliquer sur « acheter » ajoute un produit au panier dâachats. Les composants ont besoin de « se souvenir » de certaines choses : la valeur saisie, lâimage active, le panier dâachats. En React, ce type de mĂ©moire spĂ©cifique au composant est appelĂ© Ă©tat.
Vous pouvez ajouter un état à un composant avec un Hook useState
. Les Hooks sont des fonctions spĂ©ciales qui permettent Ă vos composants dâutiliser des fonctionnalitĂ©s de React (lâĂ©tat en est une). Le Hook useState
vous permet de dĂ©clarer une variable dâĂ©tat. Il prend lâĂ©tat initial en argument et renvoie une paire de valeurs : lâĂ©tat actuel et une fonction qui vous permet de le modifier.
const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);
Voici comment une galerie dâimages utilise et met Ă jour lâĂ©tat lors dâun clic :
import { useState } from 'react'; import { sculptureList } from './data.js'; export default function Gallery() { const [index, setIndex] = useState(0); const [showMore, setShowMore] = useState(false); const hasNext = index < sculptureList.length - 1; function handleNextClick() { if (hasNext) { setIndex(index + 1); } else { setIndex(0); } } function handleMoreClick() { setShowMore(!showMore); } let sculpture = sculptureList[index]; return ( <> <button onClick={handleNextClick}> Suivant </button> <h2> <i>{sculpture.name} </i> par {sculpture.artist} </h2> <h3> ({index + 1} sur {sculptureList.length}) </h3> <button onClick={handleMoreClick}> {showMore ? 'Masquer' : 'Afficher'} les détails </button> {showMore && <p>{sculpture.description}</p>} <img src={sculpture.url} alt={sculpture.alt} /> </> ); }
PrĂȘt·e Ă en apprendre davantage ?
Lisez LâĂ©tat : la mĂ©moire dâun composant pour apprendre comment mĂ©moriser une valeur et la mettre Ă jour lors dâune interaction.
En savoir plusRendu et Commit
Avant que vos composants ne soient affichĂ©s Ă lâĂ©cran, React doit effectuer leur rendu. Comprendre les Ă©tapes de ce processus vous aidera Ă rĂ©flĂ©chir Ă lâexĂ©cution de votre code et Ă expliquer son comportement.
Imaginez que vos composants soient des cuisiniers dans un restaurant, assemblant des plats savoureux Ă partir dâingrĂ©dients. Dans ce scĂ©nario, React est le serveur qui prend les commandes des clients et leur apporte leurs plats. Ce processus de demande et de service de lâUI comporte trois Ă©tapes :
- Déclencher un rendu (envoyer la commande du client à la cuisine)
- Faire le rendu du composant (préparer la commande en cuisine)
- Mettre à jour le DOM (phase de Commit ; revient à déposer la commande sur la table du client)
Déclencher Faire le rendu Mettre à jour (Commit)
Illustré par Rachel Lee Nabors
PrĂȘt·e Ă en apprendre davantage ?
Lisez Rendu et Commit pour apprendre sur le cycle de vie dâune mise Ă jour de lâinterface.
En savoir plusLâĂ©tat est un instantanĂ©
Contrairement aux variables JavaScript classiques, une variable dâĂ©tat dans React se comporte davantage comme une photo instantanĂ©e. Lui affecter une nouvelle valeur ne change pas la variable dâĂ©tat que vous avez dĂ©jĂ , mais dĂ©clenche plutĂŽt un nouveau rendu. Ăa peut surprendre au dĂ©but !
console.log(count); // 0
setCount(count + 1); // EntraĂźnera un nouveau rendu avec la valeur 1
console.log(count); // Toujours 0 !
Ce comportement vous aide Ă Ă©viter des bugs subtils. Voici une petite appli de discussion. Essayez de deviner ce qui se passe si vous appuyez sur « Envoyer » dâabord, et ensuite changez le destinataire pour Bob. Quel nom apparaĂźtra dans le alert
cinq secondes plus tard ?
import { useState } from 'react'; export default function Form() { const [to, setTo] = useState('Alice'); const [message, setMessage] = useState('Hello'); function handleSubmit(e) { e.preventDefault(); setTimeout(() => { alert(`Vouz avez dit ${message} Ă ${to}`); }, 5000); } return ( <form onSubmit={handleSubmit}> <label> Ă :{' '} <select value={to} onChange={e => setTo(e.target.value)}> <option value="Alice">Alice</option> <option value="Bob">Bob</option> </select> </label> <textarea placeholder="Message" value={message} onChange={e => setMessage(e.target.value)} /> <button type="submit">Envoyer</button> </form> ); }
PrĂȘt·e Ă en apprendre davantage ?
Lisez LâĂ©tat comme un instantanĂ© pour comprendre pourquoi un Ă©tat semble « fixe » et immuable Ă lâintĂ©rieur des gestionnaires dâĂ©vĂ©nements.
En savoir plusCumuler les mises Ă jour dâun mĂȘme Ă©tat
Ce composant comporte un bug : cliquer sur « +3 » nâincrĂ©mente le score quâune seule fois.
import { useState } from 'react'; export default function Counter() { const [score, setScore] = useState(0); function increment() { setScore(score + 1); } return ( <> <button onClick={() => increment()}>+1</button> <button onClick={() => { increment(); increment(); increment(); }}>+3</button> <h1>Score: {score}</h1> </> ) }
LâĂ©tat comme un instantanĂ© en explique la raison. Affecter une nouvelle valeur Ă un Ă©tat dĂ©clenchera un nouveau rendu, mais ne change pas sa valeur dans le code en cours dâexĂ©cution. Ainsi, score
reste Ă 0
juste aprÚs avoir appelé setScore(score + 1)
.
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
Vous pouvez corriger ça en passant une fonction de mise Ă jour lorsque vous affectez une nouvelle valeur Ă lâĂ©tat. Voyez comme le remplacement de setScore(score + 1)
par setScore(s => s + 1)
corrige le bouton « +3 ». Ăa vous permet de cumuler plusieurs mises Ă jour dâun mĂȘme Ă©tat.
import { useState } from 'react'; export default function Counter() { const [score, setScore] = useState(0); function increment() { setScore(s => s + 1); } return ( <> <button onClick={() => increment()}>+1</button> <button onClick={() => { increment(); increment(); increment(); }}>+3</button> <h1>Score: {score}</h1> </> ) }
PrĂȘt·e Ă en apprendre davantage ?
Lisez Cumuler les sĂ©rie de mises Ă jour dâun mĂȘme Ă©tat pour apprendre comment cumuler plusieurs mises Ă jour dâune mĂȘme variable dâĂ©tat.
En savoir plusMettre Ă jour les objets dâun Ă©tat
Un Ă©tat peut contenir nâimporte quel type de valeur JavaScript, y compris des objets. Cependant, vous ne devez pas changer directement les objets et les tableaux que vous stockez dans lâĂ©tat React. Au lieu de cela, lorsque vous voulez mettre Ă jour un objet ou un tableau, vous devez en crĂ©er un nouveau (ou faire une copie de lâexistant), puis mettre Ă jour lâĂ©tat pour utiliser cette copie.
Généralement, vous utiliserez la syntaxe de spread ...
pour copier les objets et les tableaux que vous souhaitez modifier. Par exemple, la mise Ă jour dâun objet imbriquĂ© pourrait ressembler Ă ceci :
import { useState } from 'react'; export default function Form() { const [person, setPerson] = useState({ name: 'Niki de Saint Phalle', artwork: { title: 'Blue Nana', city: 'Hamburg', image: 'https://i.imgur.com/Sd1AgUOm.jpg', } }); function handleNameChange(e) { setPerson({ ...person, name: e.target.value }); } function handleTitleChange(e) { setPerson({ ...person, artwork: { ...person.artwork, title: e.target.value } }); } function handleCityChange(e) { setPerson({ ...person, artwork: { ...person.artwork, city: e.target.value } }); } function handleImageChange(e) { setPerson({ ...person, artwork: { ...person.artwork, image: e.target.value } }); } return ( <> <label> Nom : <input value={person.name} onChange={handleNameChange} /> </label> <label> Titre : <input value={person.artwork.title} onChange={handleTitleChange} /> </label> <label> Ville : <input value={person.artwork.city} onChange={handleCityChange} /> </label> <label> Image : <input value={person.artwork.image} onChange={handleImageChange} /> </label> <p> <i>{person.artwork.title}</i> {' par '} {person.name} <br /> (Ă {person.artwork.city}) </p> <img src={person.artwork.image} alt={person.artwork.title} /> </> ); }
Si la copie dâobjets dans le code devient fastidieuse, vous pouvez utiliser une bibliothĂšque telle que Immer pour simplifier le code :
{ "dependencies": { "immer": "1.7.3", "react": "latest", "react-dom": "latest", "react-scripts": "latest", "use-immer": "0.5.1" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }, "devDependencies": {} }
PrĂȘt·e Ă en apprendre davantage ?
Lisez Mettre Ă jour les objets dâun Ă©tat pour apprendre comment mettre Ă jour correctement les objets dâune variable dâĂ©tat.
En savoir plusMettre Ă jour les tableaux dâun Ă©tat
Les tableaux sont un autre type dâobjet modifiable en JavaScript que vous pouvez stocker dans un Ă©tat et que vous devez traiter comme Ă©tant en lecture seule. Tout comme avec les objets, lorsque vous souhaitez mettre Ă jour un tableau stockĂ© dans un Ă©tat, vous devez en crĂ©er un nouveau (ou en copier un existant), puis affecter le nouveau tableau dans lâĂ©tat :
import { useState } from 'react'; const initialList = [ { id: 0, title: 'Big Bellies', seen: false }, { id: 1, title: 'Lunar Landscape', seen: false }, { id: 2, title: 'Terracotta Army', seen: true }, ]; export default function BucketList() { const [list, setList] = useState( initialList ); function handleToggle(artworkId, nextSeen) { setList(list.map(artwork => { if (artwork.id === artworkId) { return { ...artwork, seen: nextSeen }; } else { return artwork; } })); } return ( <> <h1>Liste dâĆuvres dâart</h1> <h2>Ma liste Ă voir absolument :</h2> <ItemList artworks={list} onToggle={handleToggle} /> </> ); } function ItemList({ artworks, onToggle }) { return ( <ul> {artworks.map(artwork => ( <li key={artwork.id}> <label> <input type="checkbox" checked={artwork.seen} onChange={e => { onToggle( artwork.id, e.target.checked ); }} /> {artwork.title} </label> </li> ))} </ul> ); }
Si la copie de tableaux dans le code devient fastidieuse, vous pouvez utiliser une bibliothĂšque telle que Immer pour simplifier le code :
{ "dependencies": { "immer": "1.7.3", "react": "latest", "react-dom": "latest", "react-scripts": "latest", "use-immer": "0.5.1" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }, "devDependencies": {} }
PrĂȘt·e Ă en apprendre davantage ?
Lisez Mettre Ă jour les tableaux dâun Ă©tat pour apprendre comment mettre Ă jour correctement les tableaux dâune variable dâĂ©tat.
En savoir plusEt maintenant ?
Allez sur Réagir aux événements pour commencer à lire ce chapitre page par page !
Ou alors, si vous ĂȘtes dĂ©jĂ Ă lâaise avec ces sujets, pourquoi ne pas explorer comment gĂ©rer lâĂ©tat ?