Le hook d'état permet, comme son nom l'indique, de définir des variables d'état local.

Par exemple dans une classe, une variable d'état local représentant un nom (name) est définie ainsi:

class NameTag extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: props.initialName // 👈
    };  
}

Cependant, dans une fonction composant il est impossible de faire référence à this. Pour pallier ce problème, il est possible d'utiliser un hook via useState afin d'obtenir une variable d'état local équivalente.

Déclaration

Pour déclarer une variable d'état via useState, il suffit de faire:

function NameTag(props) {
  const [name, setName] = React.useState(props.initialName); // 👈
}

Analyse du code:

  1. const [name, setName]: deux variables sont créées à partir d'une déstructuration de tableau. La première name correspond au nom à attribué à la variable d'état locale, tandis que setName correspond à une fonction permettant de mettre à jour name.

  2. React.useState(initialName): appel de la méthode useState de React retournant un tableau contenant une variable nommée en fonction du paramètre initialName passé en props ainsi qu'une fonction permettant de mettre à jour ladite variable.

En fait, ce code 👇 est une version équivalente au code précédent en version simpliste, mais surtout plus longue. ce format n'est donc pratiquement jamais utilisé:

function NameTag(props) {
  const nameArr = React.useState(props.initialName);
  const name = nameArr[0];
  const setName = nameArr[1];
}

Exemple concret

Mise à jour

Pour mettre à jour une variable définie par un hook d'état, il suffit d'appeler la fonction retournée à cet effet.

Par exemple, si les variables nbr et setNbr ont étés crées via useState, il suffit d'appeler setNbr pour mettre nbr à jour:

<button onClick={() => setNbr(nbr + 1)}>

Dès que le bouton est cliqué, la fonction setNbr est appelée afin de mettre à jour la valeur de la variable nbr.

Exemple concret

Mise à jour async

Certaines fonctions font parfois des appels async. Dans ce cas, si une de ces fonctions est appelée plusieurs fois dans un court délai, il est possible que les variables à l'intérieur de celle-ci n'aient pas le temps de se mettre à jour entre chaque appel, ce qui peut engendrer des problèmes.

Par exemple, essayez d'appuyer 3x le plus rapidement possible sur les boutons ci-dessous 👇. Vous remarquerez que malgré les 3 clics, le nombre affiché n'a pas fluctué de 3 comme il devrait logiquement le faire:

Un faux délais async d’une demi-seconde a été ajouté.

Solution: accéder à la valeur précédente

Pour obtenir la précédente valeur d'une variable avant de la modifier, il est possible d'utiliser une fonction anonyme et de lui attribuer un paramètre. Peu importe le nom de ce paramètre, la fonction lui attribuera la plus récente valeur de la variable.

Par exemple, plutôt que de faire directement à nbr + 1, il est possible d'accéder à la précédente valeur de nbr via une fonction anonyme et son paramètre prevNbr.

const increment = async () => {
  await doSomethingAsync();
  setNbr(prevNbr => prevNbr + 1);
}

Cette stratégie permet de s'assurer que chaque appel de la fonction se base sur la valeur à jour de la variable nbr et non simplement sur sa valeur au moment de l'appel.

Par exemple, essayez à nouveau d'appuyer 3x le plus rapidement possible sur les boutons ci-dessous 👇 et remarquez comment cette fois le nombre affiché correspond au nombre de clics: