Vous êtes sur la page 1sur 7

État sous forme d'instantané

Les variables d'état peuvent ressembler à des variables JavaScript classiques dans lesquelles
vous pouvez lire et écrire. Cependant, l’état se comporte davantage comme un instantané. Le
définir ne modifie pas la variable d'état que vous avez déjà, mais déclenche un nouveau rendu.

Tu vas apprendre
 Comment la définition de l'état déclenche le rendu
 Quand et comment les mises à jour d'état
 Pourquoi l'état ne se met pas à jour immédiatement après l'avoir défini
 Comment les gestionnaires d’événements accèdent à un « instantané » de l’état

Définition des déclencheurs d'état pour les rendus


Vous pourriez penser que votre interface utilisateur change directement en réponse à un
événement utilisateur, comme un clic. Dans React, cela fonctionne un peu différemment de ce
modèle mental. Sur la page précédente, vous avez vu que l'état du paramètre demande un
nouveau rendu à React. Cela signifie que pour qu'une interface réagisse à l'événement, vous
devez mettre à jour le state .

Dans cet exemple, lorsque vous appuyez sur « envoyer », setIsSent(true)indique à React de
restituer l'interface utilisateur :

import { useState } from 'react';

export default function Form() {


const [isSent, setIsSent] = useState(false);
const [message, setMessage] = useState('Hi!');
if (isSent) {
return <h1>Your message is on its way!</h1>
}
return (
<form onSubmit={(e) => {
e.preventDefault();
setIsSent(true);

1
sendMessage(message);
}}>
<textarea
placeholder="Message"
value={message}
onChange={e => setMessage(e.target.value)}
/>
<button type="submit">Send</button>
</form>
);
}

function sendMessage(message) {
// ...
}

Voici ce qui se passe lorsque vous cliquez sur le bouton :


 Le onSubmitgestionnaire d'événements s'exécute.
 setIsSent(true)définit et met isSenten truefile d'attente un nouveau rendu.
 React restitue le composant en fonction de la nouvelle isSentvaleur.

Le rendu prend un instantané dans le temps


« Rendu » signifie que React appelle votre composant, qui est une fonction. Le JSX que vous
renvoyez à partir de cette fonction est comme un instantané de l'interface utilisateur dans le
temps. Ses accessoires, gestionnaires d'événements et variables locales ont tous été calculés en
utilisant son état au moment du rendu.

Contrairement à une photographie ou à une image de film, l’« instantané » de l’interface


utilisateur que vous renvoyez est interactif. Il inclut une logique telle que des gestionnaires
d'événements qui spécifient ce qui se passe en réponse aux entrées. React met à jour l'écran
pour correspondre à cet instantané et connecte les gestionnaires d'événements. Par
conséquent, appuyer sur un bouton déclenchera le gestionnaire de clics depuis votre JSX.

Lorsque React restitue un composant :


1. React appelle à nouveau votre fonction.

2
2. Votre fonction renvoie un nouvel instantané JSX.
3. React met ensuite à jour l'écran pour qu'il corresponde à l'instantané renvoyé par votre
fonction.
En tant que mémoire d'un composant, l'état n'est pas comme une variable régulière qui
disparaît après le retour de votre fonction. L'état « vit » en fait dans React lui-même, comme s'il
était sur une étagère !, en dehors de votre fonction. Lorsque React appelle votre composant, il
vous donne un instantané de l'état de ce rendu particulier. Votre composant renvoie un
instantané de l'interface utilisateur avec un nouvel ensemble d'accessoires et de gestionnaires
d'événements dans son JSX, tous calculés à l'aide des valeurs d'état de ce rendu !
Voici une petite expérience pour vous montrer comment cela fonctionne. Dans cet exemple,
vous pourriez vous attendre à ce que cliquer sur le bouton « +3 » incrémente le compteur trois
fois car il appelle setNumber(number + 1)trois fois.

Voyez ce qui se passe lorsque vous cliquez sur le bouton « +3 » :

import { useState } from 'react';

export default function Counter() {


const [number, setNumber] = useState(0);

return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 1);
setNumber(number + 1);
setNumber(number + 1);
}}>+3</button>
</>
)
}

Notez que cela numbern'incrémente qu'une fois par clic !

3
Le réglage de l'état ne le change que pour le prochain rendu. Lors du premier rendu,
numberc'était 0. C'est pourquoi, dans le gestionnaire de ce rendu onClick , la valeur de
numberest toujours 0même après setNumber(number + 1)avoir été appelée :

<button onClick={() => {


setNumber(number + 1);
setNumber(number + 1);
setNumber(number + 1);
}}>+3</button>

Voici ce que le gestionnaire de clics de ce bouton demande à React de faire :

1. setNumber(number + 1): numberc'est 0vrai setNumber(0 + 1).

 React se prépare à passer numberà 1lors du prochain rendu.

2. setNumber(number + 1): numberc'est 0vrai setNumber(0 + 1).

 React se prépare à passer numberà 1lors du prochain rendu.

3. setNumber(number + 1): numberc'est 0vrai setNumber(0 + 1).

 React se prépare à passer numberà 1lors du prochain rendu.

Même si vous avez appelé setNumber(number + 1)trois fois, dans ce rendu, le gestionnaire
d'événements numberest toujours 0, vous définissez donc l'état sur 1trois fois. C'est pourquoi, une fois
votre gestionnaire d'événements terminé, React restitue le composant avec numberégal à 1plutôt que
3.

Vous pouvez également visualiser cela en remplaçant mentalement les variables d'état par leurs valeurs
dans votre code. Puisque la numbervariable d'état est 0destinée à ce render , son gestionnaire
d'événements ressemble à ceci :

<button onClick={() => {


setNumber(0 + 1);
setNumber(0 + 1);
setNumber(0 + 1);
}}>+3</button>

Pour le prochain rendu, numberis 1, de sorte que le gestionnaire de clic du rendu ressemble à ceci :

<button onClick={() => {


setNumber(1 + 1);

4
setNumber(1 + 1);
setNumber(1 + 1);
}}>+3</button>

C'est pourquoi un nouveau clic sur le bouton mettra le compteur à 2, puis 3au prochain clic, et ainsi de
suite.

État au fil du temps


Essayez de deviner ce qui vous alertera en cliquant sur ce bouton :

import { useState } from 'react';

App.js:

export default function Counter() {


const [number, setNumber] = useState(0);

return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 5);
alert(number);
}}>+5</button>
</>
)
}
Si vous utilisez la méthode de substitution d'avant, vous pouvez deviner que l'alerte affiche « 0 » :

setNumber(0 + 5);
alert(0);
App.js:
import { useState } from 'react';

export default function Counter() {


const [number, setNumber] = useState(0);

return (
<>

5
<h1>{number}</h1>
<button onClick={() => {
setNumber(number + 5);
setTimeout(() => {
alert(number);
}, 3000);
}}>+5</button>
</>
)
}
L'état stocké dans React a peut-être changé au moment de l'exécution de l'alerte, mais il a été planifié à
l'aide d'un instantané de l'état au moment où l'utilisateur a interagi avec lui !

La valeur d'une variable d'état ne change jamais au cours d'un rendu, même si le code de son
gestionnaire d'événements est asynchrone. À l'intérieur de ce rendu onClick , la valeur de
numbercontinue d'être 0même après setNumber(number + 5)l'appel. Sa valeur était « corrigée »
lorsque React « prenait l'instantané » de l'interface utilisateur en appelant votre composant.

Voici un exemple de la façon dont cela rend vos gestionnaires d’événements moins sujets aux erreurs de
timing. Vous trouverez ci-dessous un formulaire qui envoie un message avec un délai de cinq secondes.
Imaginez ce scénario :

1. Vous appuyez sur le bouton « Envoyer », envoyant « Bonjour » à Alice.


2. Avant la fin du délai de cinq secondes, vous modifiez la valeur du champ « À » en « Bob ».

Qu'espérez-vous qu'il alertaffiche ? Est-ce que cela afficherait « Tu as dit bonjour à Alice » ? Ou
afficherait-il « Vous avez dit bonjour à Bob » ? Faites une supposition en fonction de ce que vous savez,
puis essayez :

App.js :
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(`You said ${message} to ${to}`);
}, 5000);

6
}

return (
<form onSubmit={handleSubmit}>
<label>
To:{' '}
<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">Send</button>
</form>
);
}
React conserve les valeurs d'état « fixes » dans les gestionnaires d'événements d'un rendu. Vous
n'avez pas à vous soucier de savoir si l'état a changé pendant l'exécution du code.

Vous aimerez peut-être aussi