Les difficultés de travailler avec Redux et leur solution

image

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 .

Exemple
const 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.

image

La magie IDE n'aidera pas
Nous 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?

image

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.

image

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

    image
  • 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.

    image
  • 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.

Source: https://habr.com/ru/post/fr459460/


All Articles