Utiliser le Hook d’état
Les Hooks sont une nouveauté de React 16.8. Ils permettent de bénéficier d’un état local et d’autres fonctionnalités de React sans avoir à écrire de classes.
La page d’introduction présentait les Hooks avec cet exemple :
import React, { useState } from 'react';
function Example() {
// Déclare une nouvelle variable d'état, que l'on va appeler « count » const [count, setCount] = useState(0);
return (
<div>
<p>Vous avez cliqué {count} fois</p>
<button onClick={() => setCount(count + 1)}>
Cliquez ici
</button>
</div>
);
}
Pour commencer à comprendre comment fonctionnent les Hooks, comparons ce code avec un exemple équivalent à base de classe.
Exemple équivalent avec une classe
Si vous avez déjà utilisé les classes en React, ce code devrait vous parler :
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>Vous avez cliqué {this.state.count} fois</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Cliquez ici
</button>
</div>
);
}
}
L’état démarre à { count: 0 }
, et nous incrémentons state.count
en appelant this.setState()
lorsque l’utilisateur clique sur le bouton. Nous utiliserons des extraits de cette classe dans tout le reste de cette page.
Remarque
Vous vous demandez peut-être pourquoi nous utilisons un compteur plutôt qu’un exemple plus réaliste. Ça nous permet tout simplement de nous concentrer sur l’API pendant que nous faisons nos premiers pas avec les Hooks.
Hooks et fonctions composants
Pour rappel, les fonctions composants en React ressemblent à ceci :
const Example = (props) => {
// Vous pouvez utiliser des Hooks ici !
return <div />;
}
ou à ça :
function Example(props) {
// Vous pouvez utiliser des Hooks ici !
return <div />;
}
Vous les connaissiez peut-être sous le nom de « composants sans état » (Stateless (Functional) Components ou SFC, NdT). Comme nous avons maintenant la possibilité d’utiliser l’état local React dans ces composants, nous préférerons le terme « fonctions composants ».
Les Hooks ne fonctionnent pas dans les classes. Mais vous pouvez les utiliser pour éviter d’écrire des classes.
Un Hook, qu’est-ce que c’est ?
Pour notre nouvel exemple, commençons par importer le Hook useState
de React :
import React, { useState } from 'react';
function Example() {
// ...
}
Qu’est-ce qu’un Hook ? Un Hook est une fonction qui permet de « se brancher » sur des fonctionnalités React. Par exemple, useState
est un Hook qui permet d’ajouter l’état local React à des fonctions composants. Nous en apprendrons plus sur les Hooks par la suite.
Quand utiliser un Hook ? Auparavant, si vous écriviez une fonction composant et que vous réalisiez que vous aviez besoin d’un état local à l’intérieur, vous deviez la convertir en classe. Désormais vous pouvez utiliser un Hook à l’intérieur de votre fonction composant. Et c’est justement ce que nous allons faire !
Remarque
Des règles spécifiques existent pour savoir quand utiliser ou ne pas utiliser les Hooks dans un composant. Nous les découvrirons dans les Règles des Hooks.
Déclarer une variable d’état
Dans une classe, on initialise l’état local count
à 0
en définissant this.state
à { count: 0 }
dans le constructeur :
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 }; }
Dans une fonction composant, nous ne pouvons pas écrire ou lire this.state
puisqu’il n’y a pas de this
. Au lieu de ça, nous appelons directement le Hook useState
dans notre composant :
import React, { useState } from 'react';
function Example() {
// Déclare une nouvelle variable d'état, que nous appellerons « count » const [count, setCount] = useState(0);
Appeler useState
, qu’est-ce que ça fait ? Ça déclare une « variable d’état ». Notre variable est appelée count
mais nous aurions pu l’appeler n’importe comment, par exemple banane
. C’est un moyen de « préserver » des valeurs entre différents appels de fonctions. useState
est une nouvelle façon d’utiliser exactement les mêmes possibilités qu’offre this.state
dans une classe. Normalement, les variables « disparaissent » quand la fonction s’achève mais les variables d’état sont préservées par React.
Qu’est-ce qu’on passe à useState
comme argument ? Le seul argument à passer au Hook useState()
est l’état initial. Contrairement à ce qui se passe dans les classes, l’état local n’est pas obligatoirement un objet. Il peut s’agir d’un nombre ou d’une chaîne de caractères si ça nous suffit. Dans notre exemple, nous voulons simplement le nombre de fois qu’un utilisateur a cliqué sur le bouton, nous passerons donc 0
comme état initial pour notre variable. (Si nous voulions stocker deux valeurs différentes dans l’état, nous appellerions useState()
deux fois.)
Que renvoie useState
? Elle renvoie une paire de valeurs : l’état actuel et une fonction pour le modifier. C’est pourquoi nous écrivons const [count, setCount] = useState()
. C’est semblable à this.state.count
et this.setState
dans une classe, mais ici nous les récupérons en même temps. Si vous n’êtes pas à l’aise avec la syntaxe que nous avons employée, nous y reviendrons en bas de cette page.
Maintenant que nous savons ce que fait le Hook useState
, notre exemple devrait commencer à être plus clair :
import React, { useState } from 'react';
function Example() {
// Déclare une nouvelle variable d'état, que nous appellerons « count » const [count, setCount] = useState(0);
Nous déclarons une variable d‘état appelée count
, et l’initialisons à 0
. React se rappellera sa valeur entre deux affichages et fournira la plus récente à notre fonction. Si nous voulons modifier la valeur de count
, nous pouvons appeler setCount
.
Remarque
Vous vous demandez peut-être pourquoi
useState
n’est pas plutôt appeléecreateState
?En fait, “create” ne serait pas tout à fait correct puisque l’état n’est créé qu’au premier affichage de notre composant. Les fois suivantes,
useState
nous renvoie l’état actuel. Autrement, ce ne serait pas un état du tout ! Il y a aussi une raison pour laquelle les noms des Hooks commencent toujours paruse
. Nous découvrirons laquelle plus tard dans les Règles des Hooks.
Lire l’état
Quand nous voulons afficher la valeur actuelle de count
dans une classe, nous récupérons la valeur de this.state.count
:
<p>Vous avez cliqué {this.state.count} fois</p>
Dans une fonction, nous pouvons directement utiliser count
:
<p>Vous avez cliqué {count} fois</p>
Mettre à jour l’état
Dans une classe, nous devons appeler this.setState()
pour mettre à jour l’état count
:
<button onClick={() => this.setState({ count: this.state.count + 1 })}> Cliquez ici
</button>
Dans une fonction, nous récupérons directement setCount
et count
comme variables, nous n’avons donc pas besoin de this
:
<button onClick={() => setCount(count + 1)}> Cliquez ici
</button>
En résumé
Il est maintenant temps de récapituler ce que nous avons appris ligne par ligne et vérifier que nous avons bien compris.
1: import React, { useState } from 'react'; 2:
3: function Example() {
4: const [count, setCount] = useState(0); 5:
6: return (
7: <div>
8: <p>Vous avez cliqué {count} fois</p>
9: <button onClick={() => setCount(count + 1)}>10: Cliquez ici
11: </button>
12: </div>
13: );
14: }
- Ligne 1 : nous importons le Hook
useState
depuis React. Il nous permet d’utiliser un état local dans une fonction composant. - Ligne 4 : dans le composant
Example
, nous déclarons une nouvelle variable d’état en appelant le HookuseState
. Il renvoie une paire de valeurs que nous pouvons nommer à notre guise. Ici, nous appelons notre variablecount
puisqu’elle contient le nombre de clics sur le bouton. Nous l’initialisons à zéro en passant0
comme seul argument àuseState
. Le second élément renvoyé est une fonction. Elle nous permet de modifier la variablecount
, nous l’appellerons doncsetCount
. - Ligne 9 : quand l’utilisateur clique, nous appelons
setCount
avec une nouvelle valeur. React rafraîchira le composantExample
et lui passera la nouvelle valeur decount
.
Ça fait peut-être beaucoup à digérer d’un coup. Ne vous pressez pas ! Si vous vous sentez un peu perdu·e, jetez un nouveau coup d’œil au code ci-dessus et essayez de le relire du début à la fin. Promis, une fois que vous essaierez « d’oublier » la manière dont fonctionne l’état local dans les classes, et que vous regarderez ce code avec un regard neuf, ça sera plus clair.
Astuce : que signifient les crochets ?
Vous avez peut-être remarqué les crochets que nous utilisons lorsque nous déclarons une variable d’état :
const [count, setCount] = useState(0);
Les noms utilisés dans la partie gauche ne font pas partie de l’API React. Vous pouvez nommer vos variables d’état comme ça vous chante :
const [fruit, setFruit] = useState('banane');
Cette syntaxe Javascript est appelée « déstructuration positionnelle ». Ça signifie que nous créons deux nouvelles variables fruit
et setFruit
, avec fruit
qui reçoit la première valeur renvoyée par useState
, et setFruit
qui reçoit la deuxième. C’est équivalent au code ci-dessous :
var fruitStateVariable = useState('banana'); // Renvoie une paire
var fruit = fruitStateVariable[0]; // Premier élément dans une paire
var setFruit = fruitStateVariable[1]; // Deuxième élément dans une paire
Quand nous déclarons une variable d’état avec useState
, ça renvoie une paire (un tableau avec deux éléments). Le premier élément est la valeur actuelle, et le deuxième est une fonction qui permet de la modifier. Utiliser [0]
et [1]
pour y accéder est un peu déconcertant puisqu’ils ont un sens spécifique. C’est pourquoi nous préférons plutôt utiliser la déstructuration positionnelle.
Remarque
Vous vous demandez peut-être comment React sait à quel composant
useState
fait référence étant donné que nous ne lui passons plus rien de similaire àthis
. Nous répondrons à cette question ainsi qu’à plein d’autres dans la section FAQ.
Astuce : utiliser plusieurs variables d’état
Déclarer des variables d’état comme une paire de [quelquechose, setQuelquechose]
est également pratique parce que ça nous permet de donner des noms différents à des variables d’état différentes si nous voulons en utiliser plus d’une :
function ExampleWithManyStates() {
// Déclarer plusieurs variables d'état !
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banane');
const [todos, setTodos] = useState([{ text: 'Apprendre les Hooks' }]);
Dans le composant ci-dessus, nous avons age
, fruit
, et todos
comme variables locales, et nous pouvons les modifier indépendamment les unes des autres :
function handleOrangeClick() {
// Similaire à this.setState({ fruit: 'orange' })
setFruit('orange');
}
Utiliser plusieurs variables d’état n’est pas obligatoire. Les variables d’état peuvent tout à fait contenir des objets et des tableaux, vous pouvez donc toujours regrouper des données ensemble. Cependant, lorsque l’on modifie une variable d’état sa valeur est remplacée et non fusionnée, contrairement à this.setState
dans les classes.
Découvrez les raisons de préférer séparer vos variables d’état dans la FAQ.
Prochaines étapes
Dans cette section, vous avez appris à utiliser un des Hooks fournis par React, appelé useState
. Nous y ferons parfois référence sous le terme « Hook d’état ». Il nous permet d’ajouter un état local à des fonctions composants React—ce qui est une première !
Nous en avons également appris un peu plus sur la nature des Hooks. Les Hooks sont des fonctions qui nous permettent de « nous brancher » sur des fonctionnalités React depuis des fonctions composants. Leur noms commencent toujours par use
, et il y a encore beaucoup de Hooks que nous n’avons pas encore vus !
Continuons maintenant en découvrant le prochain Hook : useEffect
. Il vous permet de déclencher des effets de bord dans les composants, ce qui est similaire aux méthodes de cycle de vie dans les classes.