Ne pas abuser du state

Ne pas abuser du state

Quand j'ai appris React en parcourant mille tuto sur le net, je suis tombé sur pas mal d'exemple d'utilisation du state. Loin de moi l'envie de les critiquer, ils m'ont beaucoup appris, mais quand je revois les notes que j'avais noté à l'époque, je me rends compte qu'il y a certains problèmes quant à l'utilisation du State. Dans ce petit tuto, je vais vous expliquer pourquoi il ne faut pas en abuser, et comment bien l'utiliser.

Ryan Djoher

02/02/2021 - 6 minutes de lecture

State by me

Le state, c'est un peu la mémoire d'un script javascript. Si vous ne savez pas ce qu'est un state, c'est que vous n'avez pas encore appris React. Mais je parie ma Playstation 4 que si vous êtes là, c'est que vous connaissez déjà React.

Les cas que l'on voit beaucoup dans les tutoriels, c'est les formulaires. Et c'est normal car c'est une façon très pratique pour l'utilisation d'un State. Du coup, je vais vous faire un petit code formulaire sans prétention afin que vous compreniez pourquoi il c'est important de bien utiliser le State.

import React, { useState } from 'react';

function App() {

  const [lastname, setLastname] = useState(null)
  const [firstname, setFirstname] = useState(null)
  const [city, setCity] = useState(null)

  const changeLastName = e => {
    setLastname(e.target.value)
  }

  const changeFirstName = e => {
    setFirstname(e.target.value)
  }

  const changeCity = e => {
    setCity(e.target.value)
  }

  const confirm = e => {
    e.preventDefault()
    console.log(`On envoit ${lastname}, ${firstname} et ${city}`)
  }

  return (
    <div>
      <h1>Mon petit formulaire à moi</h1>
      <form onSubmit={confirm}>
        <label htmlFor="lastname">Nom :</label> 
        <input type="text" id="lastname" onChange={changeLastName}/>
        <label htmlFor="firstname">Prénom :</label> 
        <input type="text" id="firstname" onChange={changeFirstName}/>
        <label htmlFor="city">Ville :</label> 
        <input type="text" id="city" onChange={changeCity}/>
        <button type="submit">Valider</button>
      </form>
    </div>
  );
}

export default App;

Ici, on entre son nom, son prénom et sa ville puis on valide afin d'envoyer ces infos là où on souhaite. Ce genre précis de cas de figure, on le voit beaucoup dans mes exemples. En entrant des lettres dans l'input du nom, la fonction "changeLastName" qui est dans le "onchange" se lance et envoi directement les lettres dans cette fonction qui lui, utilisera le "setLastname" pour mettre la variable "lastName" à jour.

Ne faites jamais ça !

N'oubliez pas une chose : à chaque fois que le state se met à jour, il y a un re-render de votre page. Le dom virtuel est mis à jour, il est compré au vrai dom... bref, vous savez déjà tout ça.

Un re-render est utile si on veut mettre à jour des informations qui sont affichés sur la page (ou pour plein d'autres choses mais ce n'est pas le sujet). Or dans ce cas de figure, l'affichage de notre page ne change pas quand on entre notre nom. Ce n'est pas comme si dans le titre, on voulait que le nom soit mis à jour en même temps que la personne la tape sur le input. Ce qu'on veut, c'est stocké en temps réelle le nom quelque part pour qu'on puisse le récupérer lorsque l'utilisateur validera le formulaire.

C'est donc ici une mauvaise pratique du state, car on fait un re-render inutile à chaque fois qu'on tape une lettre dans les input. Et en termes de performance, c'est pas top.

La solution, c'est sans state.

C'est bien beau de vous dire qu'il ne faut pas utiliser le state de cette manière, mais si on veut faire exactement pareille dans l'esprit, comment on fait sans le state ? Facile :

import React from 'react';

function App() {

  let lastname
  let firstname
  let city

  const changeLastName = e => {
    lastname = e.target.value
  }

  const changeFirstName = e => {
    firstname = e.target.value
  }

  const changeCity = e => {
    city = e.target.value
  }

  const confirm = e => {
    e.preventDefault()
    console.log(`On envoit ${lastname}, ${firstname} et ${city}`)
  }

  return (
    <div>
      <h1>Mon petit formulaire à moi</h1>
      <form onSubmit={confirm}>
        <label htmlFor="lastname">Nom :</label> 
        <input type="text" id="lastname" onChange={changeLastName}/>
        <label htmlFor="firstname">Prénom :</label> 
        <input type="text" id="firstname" onChange={changeFirstName}/>
        <label htmlFor="city">Ville :</label> 
        <input type="text" id="city" onChange={changeCity}/>
        <button type="submit">Valider</button>
      </form>
    </div>
  );
}

export default App;

La solution, c'est de simplement remplacé le useState par de simple variable comme on a appris à le faire lors de nos premiers jours d'apprentissage en développement web / programmation. Tout fonctionne exactement de la même manière. Bien entendu, si vous avez besoin d'afficher des choses différents à chaque fois que l'utilisateur tape une nouvelle lettre dans les input ou si des composants sont dépendants de ces input, alors l'utilisation du state est justifié. Mais là, pas besoin de déranger les performances de notre site.

J'espère, avec cet article, vous avoir montré qu'il ne fallait pas abuser inutilement du state et que vous y voyez un peu plus clair quant à sa réelle utilisation. N'hésitez pas à m'envoyer un mail si vous avez des questions ou des suggestions.