Aller au contenu principal

Recapt Mai 2022

· 6 minutes de lecture
Damien Buchet

Les nouveautés et nouvelles qu'il ne fallait pas manquer sur l'écosystème React / Javascript, de Mai 2022 🤗

Au programme ce mois-ci :

  • Une nouvelle proposition de hook useEvent
  • Storybook: Webpack vs Vite
  • Un nouveau système de routing pour NextJS
  • Les packages / librairies / outils à surveiller
  • Et on termine par le WTF JS?

Un nouveau hook useEvent ?

useEvent serait un nouvel hook, sans tableau de dépendance, qui permet d'avoir une référence persistante à une fonction, et qui utiliserait toujours la valeur courante des variables dans son corps d'exécution. Bon. Une fois ça dit, concrètement à quoi ça sert, et comment ça se matérialise ?

Revenons un peu en arrière, sur comment marche la comparaison de props en React. J'ai déjà écris un article dessus

const Cart = () => {
const [total, setTotal] = useState(0);
const onClickBuy = {
console.log(total);
};

return (
...
<BuyButton onClick={onClickBuy} />
);
}

Dans l'exemple ci-dessous, nous aurons notre bouton BuyButton qui sera re-render à chaque render de notre Cart car la fonction onClickBuy est redéfinie à chaque fois. Pour changer ca, nous utilisons actuellement useCallback

const Cart = () => {
const [total, setTotal] = useState(0);
const onClickBuy = useCallback(() => {
console.log(total);
}, [total]);

return (
...
<BuyButton onClick={onClickBuy} />
);
}

Nous avions donc dans notre tableau de dépendance de useCallback le total. Ce qui veut dire qu'à chaque fois que ce total change, onClickBuy est redéfini, et donc BuyButton sera également re-render.

Si nous omettons total dans notre tableau de dépendance, onClickBuy ne sera jamais redéfini, mais la valeur de total est figée lors de la définition de la fonction. C'est à dire que même si vous faites varier le total pour avoir 10, onClickBuy affichera toujours 0, la valeur initiale de total lorsque onClickBuy a été définie.

Alors useEvent donc ?

const Cart = () => {
const [total, setTotal] = useState(0);
const onClickBuy = useEvent(() => {
console.log(total);
});

return (
...
<BuyButton onClick={onClickBuy} />
);
}
  • useEvent est donc sans tableau de dépendance (comme vous pouvez le voir)
  • useEvent permet d'avoir une référence persistante. C'est à dire qu'à chaque re-render de notre Cart, onClickBuy ne sera PAS redéfini, et donc BuyButton ne sera pas re-render
  • useEvent utilise toujours la valeur courante des variables. Ce qui veut dire que total ici sera bien la valeur courante de total et non pas la valeur de total au moment de la définition de onClickBuy

Alors est-ce la fin de useCallback ? Pas tout à fait. Très clairement une grande quantité de useCallback va pouvoir être transformé en useEvent. Mais useCallback DEVRA être conservé lorsque vous retournez du JSX. J'aurai certainement l'occasion d'en reparler plus tard.

Si vous souhaitez en lire plus sur cet RFC, ca se passe par ici !

StoryBook : Webpack vs ViteJS

Après Gatsby, c'est au tour de Storybook de se questionner sur Webpack vs ViteJS. Et le moins que l'on puisse dire, c'est que le résultat de leur benchmark est... surprenant !

En effet, ViteJS et à chaque fois moins performant que Webpack (sauf pour le HMR). Storybook compte proposer aux développeurs d'utiliser Webpack ou ViteJS comme ils veulent via la configuration.

Pour lire tout le benchmark, c'est par ici !

Proposition d'un nouveau système de routing pour NextJS

NextJS souhaite changer son système de routing, pour tirer parti des dernières fonctionnalités de React18, et des ServerComponents

Ce changement leur permettrait également de grouper les potentiels fetch plutot que de les executer en cascade, un peu comme le propose Remix

Pour ce faire, ils proposent de continuer à garder le répertoire /pages qui sert actuellement au routing, et de rajouter un répertoire /app qui activerait automatiquement la nouvelle architecture. Les 2 systèmes seraient viable en parallèle pour permettre une adaptation (et adoption) incrémentale de votre code.

Cette RFC est annoncée comme la plus grosse mise à jour de NextJS depuis sa création en 2016, et on devrait en savoir plus également rapidement. Pour en lire plus à ce sujet, c'est par ici !

Packages / Librairies

  • FortuneSheet Une spreadsheet (Google Sheet / Excel like) comme simple composant React, qui a l'air bien poussé.
  • Loaders Des loaders / spinners, légers et configurables, le tout en composants React.
  • useClampText Un hook pour générer facilement des "voir plus" sur des textes, qui prend en compte le multiligne.
  • ReactTable passe en v8 et devient TanStack Table
  • Antares SQL. Client SQL open source et gratuit. Une bonne alternative au performant (mais payant) TablePlus
  • IT Tools Une toolbook pour l'IT qui permet de faire... plein de choses ! Des générateurs en tout genre (token, qr code,...), convertisseurs (couleur, casse, base64,...)

WTF JS?

Que va afficher ce console.log ?

Math.min() > Math.max();
Afficher la solution et les explications !

😱 true 😱

Alors pourquoi ?

Et bien il faut comprendre comment marchent ces fonctions Math.min et Math.max. Prenons Math.min, il va comparer tous les nombres passés en arguments pour définir lequel est le plus petit. En gros une petite boucle (simplifiée évidemment) dans le genre :

const totalArguments = arguments.length;
let min = ?; // On verra ca plus tard :)
for (i = 0; i<totalArguments; i++) {
if (arguments[i] < min) min = arguments[i];
}

Mais comment initialiser ce min pour effectuer la première comparaison ? Pour être sûr que le premier argument satisfasse toujours la condition, et soit donc le nouveau min ? On aurait pu penser qu'une simple condition aurait suffit :

const totalArguments = arguments.length;
let min;
for (i = 0; i<totalArguments; i++) {
if (i === 0) min = arguments[i];
else {
if (arguments[i] < min) min = arguments[i];
}
}

Mais ce n'est pas ce qui a été fait, ce min est initialisé à... Infinity. Donc en effet, quel que soit le nombre que vous passez comme argument, ca sera toujours plus petit que Infinity !

Sauf que si on ne passe aucun argument à notre fonction... et bien Math.min() retourne Infinity.

Et de la même façon (mais dans l'autre sens), Math.max retourne -Infinity si appelé sans argument.

Et Infinity > -Infinity, donc Math.min() > Math.max() 🤘

Ne manquez pas un article !

Envie de recevoir par email mes derniers articles et Recapt ?

Essayez de taper register <votre adresse email> dans la console 🎉