Redux parmi nous
C'est l'un des
gestionnaires d'État les plus populaires.
Il est facile à utiliser, transparent et prévisible. Avec lui, vous pouvez organiser le stockage et la modification des données. Et si nous supposons que les
actions `et les
réducteurs font partie de
redux` a, alors nous pouvons dire sans exagération qu'il est le détenteur de toute la logique du domaine (aka la logique métier) de nos applications.
Est-ce que tout est si rose?
Malgré toute sa simplicité et sa transparence, l'utilisation de
redux présente un certain nombre d'inconvénients ...
Les données dans l'
état «
redux» et se trouvent dans un simple objet
javascript et peuvent être obtenues de la manière habituelle, il vous suffit de
connaître le chemin .
Mais comment organiser ces données? Il n'y a que 2 options: une
liste plate et un
modèle hiérarchique .
Une liste plate est une excellente option pour une application dans laquelle il n'y a, par exemple, qu'un compteur ... Pour quelque chose de plus sérieux, nous avons besoin d'une structure hiérarchique. De plus, chaque niveau de données aura moins de connaissances que le précédent. Tout est logique et compréhensible, mais le
chemin vers les données devient composite .
Exempleconst dataHierarchy = { user: { id, name, experience, achievements: { firstTraining, threeTrainingsInRow, }, }, training: { currentSetId, status, totalAttemptsCount, attemptsLeft, mechanics: { ... }, }, };
Ici, sous la clé utilisateur, les données utilisateur sont stockées, en particulier les réalisations. Mais les réalisations n'ont pas besoin de connaître le reste des données de l'utilisateur.
De la même manière, les mécanismes spécifiques de la formation n'ont pas besoin de savoir combien de tentatives l'utilisateur a laissées - ce sont des données de formation en général.
La présence d'une structure de données hiérarchique et l'absence d'une approche modulaire de ces données conduit au fait que
partout où ces données sont utilisées,
il est nécessaire de connaître le chemin d'
accès complet à celles-ci. En d'autres termes, cela crée une
cohésion de la structure de stockage de données et de ses structures d'affichage et conduit à des difficultés avec le refactoriseur de chemin et / ou la réorganisation de la structure de données.

La magie IDE n'aidera pasNous pouvons dire qu'il existe maintenant de puissants IDE qui changent les chemins avec une seule commande, mais peu peuvent changer plusieurs clés imbriquées d'un objet ou comprendre qu'une partie du chemin se trouve dans une variable.
Un autre défi est le test. Oui, il y a un article séparé dans la documentation pour les tests
redux , mais maintenant il ne s'agit pas de tester des artefacts individuels comme le
réducteur et l'
action-creater .
Les données, les
actions et les
réducteurs sont généralement interconnectés. Et un arbre de données logiquement liées est souvent servi par plusieurs
réducteurs , qui doivent être testés, y compris ensemble.
Ajouter à cette liste des
sélecteurs dont les résultats dépendent notamment du travail des
réducteurs ...
En général, vous pouvez tester tout cela, mais vous devez faire face à un tas d'artefacts qui ne sont interconnectés que par la logique et les conventions.
Et si nous arrivions à une structure, par exemple, avec des données utilisateur, y compris des listes d'amis, des chansons préférées et quelque chose d'autre, ainsi que la fonctionnalité de les changer via des
réducteurs d'action . Peut-être que nous avons même écrit un tas de tests pour toutes ces fonctionnalités. Et maintenant, dans le prochain projet, nous avons besoin de la même chose ...
Comment coder à moindre coût?Rechercher une solution
Afin de comprendre comment préserver les avantages de
redux et éliminer les inconvénients décrits, vous devez comprendre de quoi il dépend dans le cycle de vie des données:
- Événements de rapport d'action, personnalisés et plus
- Le réducteur réagit aux actions et change ou ne change pas l'état des données
- La modification des données est un événement en soi et peut entraîner la modification d'autres données.
Dans ce cas, le contrôleur est une abstraction qui traite à la fois les actions de l'utilisateur et les modifications de données dans le
magasin . Il ne doit pas du tout être une classe distincte, en règle générale, il est réparti par composants.
Combinez l'ensemble du zoo de Redux dans une boîte noire
Mais que se passe-t-il si nous enveloppons les
actions , les
réducteurs et les
sélecteurs dans un seul module et que nous lui
apprenons à ne pas dépendre du chemin spécifique pour l'emplacement de ses données?
Que faire si toutes
les actions
utilisateur , par exemple, sont validées en appelant la méthode d'instance:
user.addFriend (friendId) ? Et les données sont obtenues via getter:
user.getFriendsCount () ?
Et si nous pouvons importer toutes les fonctionnalités de l'utilisateur avec une simple
importation ?
const userModule from 'node_modules/user-module';
Est-ce pratique? Surtout étant donné que pour cela, vous n'avez pas besoin d'écrire un tas de code supplémentaire:
Le package
npm redux-module-creator fournit toutes les fonctionnalités pour créer
des modules redux faiblement couplés, réutilisables et testés .
Chaque module se compose d'un
contrôleur , d'un
réducteur et d'une
action et présente les caractéristiques suivantes:
- s'intègre dans le magasin via un appel à la méthode intégrateur, et pour changer le lieu d'intégration, il suffit de changer uniquement le lieu de l'appel de l'intégrateur et son paramètre

- le contrôleur a une connexion avec sa partie des données dans le magasin , se souvenant du chemin qui est passé à l' intégrateur () une fois. Cela élimine le besoin de le savoir lors de l'utilisation des données.

- le contrôleur est titulaire de tous les sélecteurs, adaptateurs, etc. nécessaires
- pour suivre les modifications, il est possible de s'abonner aux modifications de vos propres données
- les réducteurs peuvent utiliser le contexte d'appel - une instance du module et en obtenir les types d'action appartenant au module. Cela élimine le besoin d'importer un tas d' actions et réduit le risque d'erreur.
- les actions obtiennent le contexte d'utilisation, car elles font partie de l'instance du module: maintenant ce n'est plus seulement trainingFinished , mais readingModule.actions.trainingFinished
- l'action existe désormais dans l'espace de noms des modules, ce qui vous permet de créer des événements avec le même nom pour différents modules
- chaque module peut être instancié plusieurs fois, et chaque instance est intégrée dans différentes parties du magasin
- Les actions des différentes instances de module ont un type d' action différent - vous pouvez répondre aux événements d'une instance spécifique
En conséquence, nous obtenons une boîte noire qui peut gérer ses données elle-même et possède des poignées pour communiquer avec du code externe.
En même temps, c'est le même
redux , avec son flux de données unidirectionnel, sa transparence et sa prévisibilité.
Et comme ce sont tous les mêmes redux et tous les mêmes
réducteurs , vous pouvez créer à partir d'eux la structure requise par la logique du domaine d'application.