Stop bashing Redux
"Redux est mort", "Redux c'est trop compliqué", "Redux ça sert à rien"… que n'a-t-on pas entendu ? Il est de bon ton de brocarder Redux.
Pourtant cette librairie reste bien utile, sinon incontournable, pour qui doit créer une SPA (Single Page Application) un peu ambitieuse. Et que ce soit dit : il n'y a pas de mauvaise DX, il n'y a que de mauvais usages de Redux.
Mais au fait… pourquoi Redux ?
Le sujet, c'est la communication entre composants. Illustrons la chose avec une application React, dans un monde où Redux n'existerait pas :
- La communication du parent vers l'enfant passe par les props ;
- Réciproquement, de l'enfant vers le parent, on utilise les callback props ;
- Et entre composants frères, il convient de passer par le composant parent, en combinant props et callback props. Mais cela oblige aussi le parent à maintenir un nouvel état applicatif.
Ce pattern est connu sous le nom de communication via l'ancêtre commun. Au premier degré, c'est déjà tout un fatras, alors imaginez le travail quand il faut faire communiquer des composants cousins via leur grand-père : bonjour le props drilling. Autant dire que la solution ne passe pas à l'échelle.
Il existe des alternatives, plus ou moins expérimentales, mais la simplicité veut qu'on utilise les contextes de React. Et quand on pousse un peu le sujet, que l'on recherche un certain systématisme, on en vient vite à Redux.
Redux est donc une librairie de gestion de l'état applicatif d'une SPA. Elle propose un contrat pour faire évoluer cet état de manière immuable, afin que chaque mise à jour déclenche bien un cycle de rendu visuel. Redux est indépendant des librairies et frameworks de vues : pour l'utiliser au sein d'une application React, par exemple, vous devrez utiliser le connecteur react-redux (qui, lui, utilise les contextes).
À bien y regarder d'ailleurs, Redux en tant que tel n'offre aucune garantie d'immutabilité, cette dernière reposant sur un gentlemen agreement. Autrement dit, si vous voulez muter le state avec vos mains pleines de doigts, vous le pouvez (mais aïe). Si, en revanche, vous voulez de l'immutabilité contrainte, vous devrez utiliser des librairies telles qu'Immutable ou Immer (embarqué dans le Redux Toolkit).
Notez enfin que le contrat de Redux repose sur de l'event sourcing, mais on pourrait imaginer faire différemment : passer un reducer en paramètre, par exemple, à combiner avec le concept de lentilles, issu de la programmation fonctionnelle.
Mais revenons à notre point de départ : encore faut-il savoir se servir de Redux. Voici donc 5 recommandations pour vous aider à en tirer le meilleur parti :
- N'utilisez Redux que si vous en avez vraiment besoin, parce que oui, ça apporte de la complexité ;
- Ne "remontez" pas tous les états dans Redux : les états locaux doivent rester locaux ;
- Connectez les composants au niveau le plus bas possible, sinon props drilling again et vous perdez l'intérêt de Redux ;
- Normalisez le state en créant des "slices", comme vous créeriez des tables dans une base de données SQL ;
- Faites de cette couche applicative une architecture hexagonale, en injectant les dépendances dans les thunks.
Un dernier mot, parce que moi aussi j'ai le droit de basher un peu Redux : aujourd'hui, la documentation officielle recommande d'utiliser une surcouche, le Redux ToolKit (RTK). Cette dernière pose réellement problème à mes yeux, en ce qu'elle pousse à l'utilisation de thunks plutôt que des reducers de haut niveau, transverses aux slices.
Et puis parce que la chose ressemble de plus en plus un framework 🤮