Blog des Gens Compliqués

React, c'est pas ce que je préfère

07/10/2020 19:03:54+02:00|Par DkVZ
5 minutes de lecture (facile)

J'ai déjà parlé deux ou trois fois de React, mais je m'étais jamais mis dans les bottes de quelqu'un qui doit l'apprendre en 2020 comme première techno frontend.

Quand j'ai découvert le truc, j'étais vraiment pas fan, particulièrement à cause du JSX et de la confusion du CSS qui se trouvait partout, dans des fichiers séparés, dans des variables dans le composant, créé par une fonction, ...

Bon, je pense que le fait que je captais rien à Webpack n'aidait pas non plus.

Et puis il y a ma vieille aversion aux systèmes de gestion de dépendances. Effacer un projet React qui vient d'être créé avec

npx create-react-app UNE_APP_REACT

Sous Windows, ça prend genre 30 secondes, même sur un SSD M.2. Bon j'avoue que sous Linux c'est quasi immédiat et à mon avis c'est pareil sur Mac. Mais quand même, 45000 fichiers???

Nombre de fichiers dans une app React fraichement créée
On dit parfois que Windows 95 est plus petit que Chome, mais Chrome est plus petit qu'une appli React vide. Et ouais les gens.

Je me suis un peu calmé depuis mes années de détestage de React. D'autant plus que la librairie en question n'a pas baissé en popularité. Au contraire, React est plus populaire que jamais.

J'en parle de manière beaucoup plus nuancée dans ma gigantissimique revue des frameworks 2019-2020.

J'évite d'y parler de hooks mais je tombe tout de même sur l'histoire où setInterval ne fonctionne pas dans le corps d'un composant fonctionnel et je résous le truc à ma manière sans utiliser la méthode préconisée qui est d'utiliser useEffect en comprenant bien qu'en fait tout ce qui est asynchrone ou utilise des timers n'est jamais censé être directement dans le corps de la fonction composant.

Dit comme ça, ça a l'air simple. Mais ça n'est expliqué comme ça nulle part. La doc parle "d'effets de bord". C'est quoi un effet de bord?

Bon après, on s'en fout, personne n'a lu mon article. Mais tout de même, j'avais vraiment pas tout compris à useEffect en général (j'ai toujours pas tout compris hein, je précise).

Avant, on avait les composants "classe", et, par exemple, exécuter quelque chose avant que le composant ne soit démonté (par ex. pour effectuer un nettoyage particulier), il y avait les méthodes de cycle de vie comme componentWillUnmount:

class TrucMachin extends Component {

  render() {
    return (<blink>COUCOU</blink>)
  }

  componentWillUnmount() {
    console.log('Au revoir monde')
  }

}

Moi je trouve ça plutôt clair. Comment on fait la même chose avec un hook?

Je vous explique: il s'agit d'appeler useEffect, en lui donnant en argument une fonction qui retourne une autre fonction qui contient le code à exécuter lors du démontage. Ah oui il faut aussi lui donner un tableau vide comme second argument. Si je vous jure.

useEffect(() => {
  return () => {
    console.log('Au revoir monde')
  }
}, [])

Je suis un peu de mauvaise foi parce qu'il y a évidemment une logique derrière tout ça qui colle avec le fonctionnement de useEffect, mais à vue de nez vous trouver que c'est du joli code ça?

Si vous devez expliquer ce truc à quelqu'un qui vient du Java ou C#, c'est tout de suite parti dans les fonctions anonymes qui renvoient une autre fonction anonyme et alors aussi il y a un tableau vide qu'on-sait-pas-trop-pourquoi-il-est-là-et-ou-nécessaire.

Alors, oui, pour bien faire il faut juste expliquer ce que ça fait ce useEffect mais on est tout de suite parti dans des histoires de tableaux de fonctions (ATTEND ON PEUT FAIRE DES TABLEAUX DE FONCTIONS???) et de cycle d'updates de React et smqlkfjmdksjfhqlksdjfh ils vont plus rien comprendre.

C'est un peu ce que je reproche à React, c'est fort JAVASCRIPT DANS TA FAAAAAAAAACE TIIIIIIEEEEENS BOUFFFEEEE tout de suite avec absolument tous les trucs étranges que JavaScript cache dans son short (y compris machin && autreTruc qui ne résulte pas nécessairement en un booléen et est super utilisé en JSX et les histoires de map() pour générer des listes).

Même quand on pense que les composant classe ça va être plus facile, il y a toute l'histoire de this et bind() et les gestionnaire d'évènements et éventuellement expliquer la différence entre tous ces trucs:

<button onClick={uneFonction}>Clique moi</button>
<button onClick={() => uneFonction()}>Clique moi</button>
<button onClick={uneFonction()}>Clique moi</button>

En devant expliquer pourquoi le 3ème génère une erreur, pourquoi le mot clé this fonctionne dans le second cas mais pas nécessairement dans le premier... à moins d'ajouter un truc du genre dans le constructeur:

this.uneFonction = this.uneFonction.bind(this)

Comment tu veux expliquer ça?? Sérieusement? On assigne un membre de la classe à lui même bindé à lui même?? Comment, pourquoi? Qui? Qui sommes-nous face à l'éternité?

Puis il y a la gestion d'état... Probablement l'aspect le plus hideux de n'importe quel framework. Expliquer qu'il s'agit normalement de recréer entièrement les objets et tableaux chaque fois, ce que les "pros du React" font avec des combines infâmes du SPREAD OPERATOR et puis il y a Redux.

J'en parle pas trop ici parce que je vais y consacrer tout un article. Mais regardez moi cet extrait de code de la doc officielle sur comment bien modifier ton state de manière immutable:

function insertItem(array, action) {
  return [
    ...array.slice(0, action.index),
    action.item,
    ...array.slice(action.index)
  ]
}

function removeItem(array, action) {
  return [...array.slice(0, action.index), ...array.slice(action.index + 1)]
}

Plus loin dans la doc ils donnent un "meilleur" exemple avec une copie du tableau via slice() puis un splice(). C'est mieux mais c'est pas vraiment mieux. En tous cas pas quand tu débute et que tu ne connais pas toutes ces subtilités, en plus que splice() est une des fonctions les plus dures à retenir en terme d'usage exact.

Je sais pas pourquoi Vue n'a pas plus de succès mais ça me rend triste et je plains tous ces qui doivent se taper React (+ Redux pour le challenge) comme première expérience JavaScript.

Et avoir une lib de gestion d'état global est tout simplement obligatoire. Je sais que les gens disent "naaah t'as pas nécessairement besoin de Redux".

Juste avoir un composant parent qui contient une liste de composants enfants, qui contiennent chacun une barre d'outils qui permet de réaliser différentes actions sur l'app, c'est l'HORREUR sans un système de state global.

Le composant toolbar doit recevoir en prop des fonctions pour chaque événement qu'il peut remonter, du coup il doit recevoir ça du composant qui gère la liste, lequel doit lui-même recevoir aussi en prop TOUS les mêmes évènements et les remonter lui-même vers le parent. Et là j'ai juste deux niveaux.

Alors oui, dans une TODO app bien plate y a pas besoin de state global (comme Redux). Rendez-la un peu moins plate pour voir.

Commentaires

Il faut JavaScript activé pour écrire des commentaires ici

Ajouter un commentaire

Votre commentaire a été ajouté
(enfin, je pense)