Hookstate

Hookstate

Il y a quelques semaines, j’avais fait un article sur le Usecontext. Outil très intéressant si notre projet ne requiert pas Redux ou tout autre state global complexe. Mais son défaut était qu’à chaque évolution de la state globale, tous les composants étaient re-rendu. Pas très grave pour un petit projet, mais quand il devient un minimum conséquent, les performances peuvent être impacter. C’est pour cette raison qu’aujourd’hui, nous allons voir ensemble un outil révolutionnaire mais tristement méconnu : le hookState.

Ryan Djoher

02/07/2021 - 7 minutes de lecture

Le changement c’est maintenant

Hookstate n’est pas très connu et si je vous en parle maintenant, c’est surtout parce que je suis tombé par hasard sur un article qui vantait ses mérites. L’avantage qu’il a face au UseContext, c’est qu’il ne force pas un nouveau rendu de tous les composants, seulement ceux qui en ont vraiment besoin. Et par rapport à Redux, c’est ses performances et sa simplicité. Voici l’article en question.

Maintenant que vous êtes presque convaincu de la puissance du Hookstate, mettons-nous tout de suite dans le code en expliquant pas à pas.

Install

Avant de rentrer dans le vif du sujet, je tiens à préciser que pour cet exemple, j’utilise le CRA (create-react-app), très pratique pour la présentation des exemples. Bref, on va passer par le npm pour installer notre petit module. Je parle de npm mais bien entendu, les utilisateurs de yarn peuvent aussi l’installer.

npm i @hookstate/core

Maintenant que notre module est installé, nous allons en premier lieu créer notre Global State. Et pour ça, rien de plus simple : un simple fichier dans le projet. Personnellement, je nomme ce fichier index.js et je le mets dans un dossier « globalState » pour plus de lisibilité. Voici ce que notre nouveau fichier contiendra.

import React from 'react';
import { createState } from '@hookstate/core';

const globalState = createState(0);

export default globalState

Rien de complexe ici : On voit qu’on a créé une variable globalState qui est un createState qui a un 0. Pour faire court, notre globalState équivaut à zero.

App

Maintenant que notre globalState est initialisé, nous allons nous intéresser aux composants. En premier lieu, on va aller dans le fichier « App.js » présent dans le dossier « src » pour y incorporer un composant que nous appellerons « Compo1 ». Voici donc notre fichier « App.js ».

import React from 'react';

import Compo1 from "./composants/compo1"

function App() {
  return (
    <div>
      <Compo1/>
    </div>
  );
}

export default App;

Et dans le composant « Compo1 » que nous allons créer dans le dossier « composants », nous allons simplement initialisé le composant.

import React from 'react';

export default function Compo1(){

  return <>
      <p>Hello Compo1</p>
  </>
}

Maintenant que tout est prêt, on va faire appel au state global que nous avons préparé il y a quelques minutes. Pour ça, on va devoir invoquer le useState et le globalState et l’afficher dans le HTML.

import React from 'react';
import { useState } from '@hookstate/core';
import globalState from "../globalState/index"

export default function Compo1(){

  const state = useState(globalState);
  return <>
      {console.log(state.get())}
  </>
}

Comme vous le voyez, on utilise le « useState » pour mettre notre « globalState » dans une nouvelle variable qui se nommera tout simplement « state ». Pour l’afficher dans le HTML, il ne faut pas juste mettre « {state} » mais « {state.get()} ». Sinon vous aurez une belle erreur. Normalement ça fonctionne et vous voyez dans votre navigateur la valeur de notre « globalState ».

On sait comment afficher, maintenant on va voir comment faire évoluer. On va simplement faire une buton qui changera ce state, toujours dans le composant 1.

import React, { useEffect } from 'react';
import { useState } from '@hookstate/core';
import globalState from "../globalState/index"


export default function Compo1(){
 
  const state = useState(globalState);
  return <>
      {state.get()}
      <button onClick={()=> state.set(1)}>Evolution</button>
  </>
}

Voilà un petit code pas très compliqué à comprendre. Sachez que lorsque nous cliquons sur le buton, notre « state » deviens 1 au lieu de 0. Et il est affiché en temps réel directement dans notre composant.

Compo2

On va maintenant faire un nouveau composant que nous nommerons « Compo2 ». Et dans ce composant, on va afficher ce fameux globalState.

import React from "react"
import { useState } from '@hookstate/core';
import globalState from "../globalState/index"

export default function Compo2(){

  const state = useState(globalState);

  return <>
      {state.get()}
    </>
}

Bien entendu, n’oubliez pas d’invoquez votre nouveau composant dans le fichier « App.js »

import React from 'react';

import Compo1 from "./composants/compo1"
import Compo2 from "./composants/compo2"


function App() {
  return (
    <div>
      <Compo1/>
     <Compo2/>
    </div>
  );
}

export default App;

Ce que le code fera maintenant, c’est d’afficher en temps réel notre « globalState » dans les deux composants, même lorsqu’il changera en cliquant sur le bouton. Le tout nous rappelle le « useContext » et c’est normal. D’ailleurs on ne comprend pas encore pourquoi on utiliserait le « hookState » au lieu du « useContext ». C’est justement ce qu’on va voir.

Le changement c’est toujours pas maintenant

On va maintenant faire un troisième composant que l’on va appeler « Compo3 ». Vous connaissez la marche à suivre : On créer le composant dans le dossier « Composant » avec les autres et on n’oublie pas de l’appeler dans le fichier « App.js ».

Dans ce troisième composant, on ne va presque rien faire, simplement mettre un « console.log » dans le rendu HTML.

import React from "react"

export default function Compo3(){

  return <>
      {console.log('Je suis le composant 3')}
    </>
}

A quoi va servir ce troisième composant ? C’est simple, il va nous servir à voir dans la console du navigateur s’il a été re-rendu ou pas. Si vous avez lu mon article sur le « useContext », on a vu que lorsque le state globale change, tous les composants était re-rendu, même les composants qui ne sont pas encapsuler dans le « Provider ». En termes de performance, c’est pas top.

Revenons à notre projet et cliquons sur le bouton pour modifier notre state globale comme on l’a fait auparavant. « Compo1 » et « Compo2 » ont eu un re-rendu car tous les deux doivent afficher la state global comme prévu. Mais la bonne nouvelle, c’est que le troisième composant n’a pas eu de re-rendu. Et c’est justement ça la force de « HookState » ! Vous voulez une preuve ? Cliquez sur le bouton et regardez dans la console de votre navigateur. Vous verrez que le message « Je suis le composant 3 » ne s’affiche pas. Il ne s’affiche pas car le composant n’a pas eu recours au re-rendu.

Et voilà, maintenant je vous ai montré la grande force du « hookState ». Je ne dis pas que c’est mieux que le « useContext » car tout dépend de vos projets mais pour un projet avec plusieurs composants, il faudra y penser fortement.