Optimiser l'initialisation d'un state de component React

Si vous utilisez React, vous connaissez très certainement le hook useState() qui permet de faire évoluer une valeur (un “état”) tout au long de la vie d’un component : celui-ci sera re-rendu à chaque changement de cette valeur. Tout simple !

Bien sûr un state peut être initialisé avec une valeur de départ. La plupart du temps, une valeur simple suffit pour l’initialiser, comme ceci par exemple :

Mais que se passe-t-il quand on veut initialiser un state avec une valeur qui doit être calculée (avec un calcul complexe) ? La première chose qui nous vient à l’esprit, c’est simplement :

On peut penser que cette fonction calcInitialTotalFromCache() ne sera appelée qu’une seule fois lors du premier rendu du component. Mais il n’en est rien !! Cette fonction sera bien appelée à chaque re-rendu du component : c’est uniquement sa valeur qui ne sera utilisée qu’une seule fois ! Vous voyez venir le le problème ?

Cette fonction étant assez coûteuse en ressource machine, l’appeler à chaque rendu peut devenir un problème pour les performances de notre application. il nous faut donc un moyen de ne l’appeler qu’une seule fois, quand elle sera utile.

Pour cela, nous pouvons utiliser ce qu’on appelle la « lazy initialization » du hook useState(), prévue par React ! Il suffit simplement de « wrapper » notre appel à la fonction dans une fonction anonyme, comme ceci :

Ainsi, nous optimisons les rendus suivants du components, car React n’appellera cette fonction qu’une seule fois.

Attention cependant, il faut utiliser la « Lazy initialization » uniquement si la valeur qu’on veut pour notre state de départ est coûteuse en ressources. Cela ne présente aucun intérêt d’utiliser une fonction de lazy initialization qui retournerait directement un simple nombre ou chaîne de caractère…

A noter aussi que cette façon de faire n’est pas utilisable dans le cas où la valeur d’initialisation issue d’un calcul coûteux est utilisé par plusieurs useState(). Dans ce cas précis, étant donné que les différents useState() sont sûrement fortement liés, il sera sans doute judicieux d’utiliser useReducer() qui offre, lui aussi, la possibilité d’initialiser du state avec une fonction d’initialisation.

Si vous avez des doutes concernant ceci, vous pouvez nous contacter et nous pourrons sûrement vous éclairer !