Redux: Pourquoi l'état ne peut pas être muté ...

Créé le 20 sept. 2015  ·  13Commentaires  ·  Source: reduxjs/redux

Salut,

J'ai lu avec intérêt sur l'immuable et comment vous ne devriez pas muter votre état. Je comprends dans une certaine mesure pourquoi c'est, pourtant, le côté "préoccupé par le temps passé à créer de nouveaux objets" est soit de ne pas comprendre dans JS à quel point c'est rapide / lent, soit il me manque autre chose.

En règle générale, créer un nouvel objet, cloner plus ou moins un ancien objet vers le nouveau plus les nouveaux ajouts (ou soustractions) d'état me semble que cela prendrait plus de temps que de simplement modifier l'état existant. J'essaie donc de comprendre pourquoi la chose immuable est si importante et affecte-t-elle quelque chose d'autre dans la chaîne que je ne vois tout simplement pas?

De plus ... Je pense que beaucoup de ce que propose Reduct pourraient être ajoutés au react-core, et peut-être même profiter de son moteur de différence DOM ... peut-être même pour aider à déterminer si l'état doit muter ou non. Je ne suis pas sûr que le processus de mutation de l'état serait plus rapide ou plus lent que de différencier l'état avec le nouvel état et de changer (muter) uniquement les parties de l'objet d'état réel qui devraient changer?

Je suis relativement nouveau dans tout cela, alors pardonnez-moi si je manque quelque chose autour de la notion de non mutation d'état. J'adore l'idée que les composants ne doivent rendre que des données immuables ... mais là encore, pour le composant, il ne se soucie pas ou ne sait pas si c'est immuable ou non ... ce sont juste des données qui sont transmises de quelque part, donc j'ai du mal à un bit avec tout l'état immuable vs mutable.

question

Commentaire le plus utile

Juste pour clarifier: l'état n'est pas profondément cloné à chaque action. Seules les parties qui ont changé sont clonées (encore une fois, pas profondément - cela dépend de ce qui a changé). Par exemple, lorsqu'un todo est modifié dans l'application TodoMVC, seul cet objet todo est cloné. Les autres objets todo sont les mêmes. Bien sûr, un nouveau tableau de liste de tâches racine est créé, pointant vers le nouvel objet, mais les objets eux-mêmes ne sont pas clonés s'ils n'ont pas changé. Par conséquent, ce n'est pas aussi cher que cela puisse paraître. De plus, lorsque cela devient coûteux (par exemple, des changements de tableau rapides), vous pouvez commencer à utiliser une bibliothèque comme Immutable.js qui a une copie très rapide grâce au partage structurel. Avec Immutable.js, la copie même de grands tableaux n'est pas vraiment si onéreuse car de gros morceaux de mémoire sont réutilisés. Enfin, que ce soit avec ou sans Immutable.js, l'immuabilité nous aide à restituer efficacement l'application car nous savons exactement ce qui a changé grâce au fait que les objets ne sont pas mutés.

Tous les 13 commentaires

Tout est question de prévisibilité et de fiabilité.

Les réducteurs dans redux sont des fonctions pures, ce qui signifie qu'ils n'ont aucun effet secondaire. Dès que vous commencez à regarder un état externe de ces fonctions, elles ne sont plus pures. Et s'ils ne sont pas purs, ils peuvent ne pas être fiables. Et cela provoque des bogues, dont beaucoup peuvent être très difficiles à localiser.

J'ai trouvé en écrivant des fonctions pures, je produis moins d'erreurs dans mon code et je suis plus productif. Et le rechargement du module à chaud (activé en utilisant des fonctions pures) est un turbocompresseur en plus de cette productivité.

Et vous recevez gratuitement des fonctionnalités telles que le voyage dans le temps, ce qui est très pratique.

Clôture en double du # 328.

Juste pour clarifier: l'état n'est pas profondément cloné à chaque action. Seules les parties qui ont changé sont clonées (encore une fois, pas profondément - cela dépend de ce qui a changé). Par exemple, lorsqu'un todo est modifié dans l'application TodoMVC, seul cet objet todo est cloné. Les autres objets todo sont les mêmes. Bien sûr, un nouveau tableau de liste de tâches racine est créé, pointant vers le nouvel objet, mais les objets eux-mêmes ne sont pas clonés s'ils n'ont pas changé. Par conséquent, ce n'est pas aussi cher que cela puisse paraître. De plus, lorsque cela devient coûteux (par exemple, des changements de tableau rapides), vous pouvez commencer à utiliser une bibliothèque comme Immutable.js qui a une copie très rapide grâce au partage structurel. Avec Immutable.js, la copie même de grands tableaux n'est pas vraiment si onéreuse car de gros morceaux de mémoire sont réutilisés. Enfin, que ce soit avec ou sans Immutable.js, l'immuabilité nous aide à restituer efficacement l'application car nous savons exactement ce qui a changé grâce au fait que les objets ne sont pas mutés.

Ahh .... voyez que ce dernier bit a du sens maintenant ... Je suppose que vous dites qu'en raison du changement de rendu du composant dû uniquement à quel état a changé, le moteur de diff / redraw de react est plus rapide en conséquence? Similaire je suppose à shouldComponentUpdate

Je suppose par cela que vous dites qu'en raison du changement de rendu du composant dû uniquement à quel état a changé, le moteur react diff / redraw est plus rapide en conséquence? Similaire je suppose à shouldComponentUpdate

Exactement, react-redux utilise un shouldComponentUpdate agressif sous le capot grâce à la garantie d'immuabilité.

@gaearon Désolé d'avoir un peu

De plus, lorsque cela devient coûteux (par exemple, des changements de tableau rapides), vous pouvez commencer à utiliser une bibliothèque comme Immutable.js qui a une copie très rapide grâce au partage structurel.

Je cherche à utiliser redux pour gérer les mises à jour d'un tableau allant jusqu'à 8000 positions et je m'attends à ce que le débit soit de l'ordre de 10 à 100 changements par 100 ms. Est-ce que je mène une bataille perdue pour essayer de gérer l'état de cette façon en utilisant Redux?
Nous prévoyons de représenter l'état via un canevas plutôt que le DOM, mais j'aimerais savoir si, d'après votre expérience, la fréquence des mises à jour nous poserait un problème ou non.

@dougajmcdonald : Ma première question est la

Au-delà de cela, je vous suggère de consulter ces ressources sur les performances liées à Redux:

Je serais également ravi d'en discuter davantage sur les canaux de discussion Reactiflux .

@markerikson Malheureusement oui, le concept du jeu implique de nombreuses mises à jour rapides d'une structure de données relativement volumineuse.
Je me rends compte que je n'étais pas tout à fait clair dans mon commentaire initial, quand je dis 10-100 changements, ceux-ci ne déclencheraient pas tous des rafraîchissements. Les 10-100 changements sont les changements d'état qui seraient représentés par un seul redessiner toutes les 100 ms.
Ma question est donc la suivante: si je devais regrouper mes mises à jour en 10 à 100 changements d'état par 100 ms, la gestion de l'état au sein de redux serait-elle en mesure de les traiter efficacement d'une manière qui serait raisonnablement complétée dans une fenêtre de 100 ms pour permettre un redessiner sans que les choses commencent à prendre du retard.
Les mises à jour d'état impliqueraient essentiellement la modification de 3-4 propriétés dans un tableau de taille 8000, nous parlerions donc de créer un nouveau tableau 1-10 fois par ms (en supposant que nous voulons garder les choses immuables) avec quelques modifications à l'un des les objets dans l'index du tableau. Les objets sont assez petits (3-4 propriétés, quelques nombres et quelques petites chaînes)

C'est pourquoi je me suis posé des questions sur les avantages de l'utilisation d'immuable, comme l'a suggéré Dan, car si nous pouvions réutiliser autant que possible le tableau, cela améliorera probablement les performances.

@dougajmcdonald : eh bien, "la gestion de l'état dans Redux" n'est en réalité que la seule fonction de réduction de racine que vous avez fournie :)

Immutable.js n'est pas une solution miracle pour améliorer les performances. Cela peut rendre certaines choses plus rapides et d'autres plus lentes. J'ai plusieurs articles sur les considérations sur les performances liées à Immutable.js que vous voudrez peut-être consulter.

Pour être honnête, compte tenu de votre cas d'utilisation, vous _pourriez_ en théorie vous en tirer davantage avec la mutation directe si vous le vouliez. Selon mon article Idiomatic Redux, Partie 1 - Mise en œuvre et intention , le noyau Redux lui-même ne se soucie pas du tout de la mutation - c'est principalement la couche d'interface utilisateur React-Redux qui le fait, ainsi que les DevTools. Maintenant, la mutation n'est pas la façon dont vous _ avez l'intention_ d'utiliser Redux, mais c'est possible.

Mon conseil personnel serait de commencer simple. Utilisez simplement des objets et des tableaux JS simples. Mettez-les à jour de manière immuable, soit «à la main», soit en utilisant l'une des nombreuses bibliothèques d'utilitaires de mise à jour immuables disponibles. Voyez comment cela fonctionne pour vous.

Ensuite, à partir de là, vous pouvez effectuer un travail d'optimisation supplémentaire en termes de traitement par lots, de réduction des expéditions, de logique de mise à jour, etc.

@markerikson empannage subtil pris sur le nez! : p Ouais, vous avez raison, le côté réducteur des choses pour le moment est fondamentalement la création et la destruction d'un assez grand tableau, mais je pense que le vrai problème est plus probablement les bits et les bobs du cycle de vie des composants de réaction lorsque l'objectif final sera un élément de canevas rendu idéalement à 60ish FPS.
Merci pour le point sur l'immuable et les points sur la mutation directe, je vais lire un peu et les considérer aussi.
Pour le moment, mon processus de réflexion consiste à déconnecter l'état redux du canevas et à lui transmettre simplement des messages via pub / sub (c'est ainsi que nous l'avons déjà connecté) juste avec plus de pièces mobiles

Je pense changer de:
pubsub> dispatch ()> reducer> redux state> react component stuff> canvas render.

À:
pubsub> état du composant local> rendu du canevas

J'utiliserai toujours redux pour le reste de l'interface utilisateur, mais peut-être pas la partie canevas de l'application.

Vos questions sont totalement valables. En fait, l'implémentation vuejs de redux appelée vuex fonctionne sous le concept de mutation. Ainsi, les «réducteurs» sont en fait appelés mutations et tant que vous modifiez l'état dans un endroit centralisé, tout devrait bien se passer. Cela se produit parce que vue ajoute des observateurs et d'autres éléments à l'état de l'application.Ainsi, comme vous l'avez mentionné, il est plus logique de modifier plutôt que de remplacer l'objet. Redux est inmutable et à la fin, les performances des deux approches réagissent aux mises à jour du DOM virtuel VS vue sont essentiellement les mêmes au point qu'il n'est pas possible de dire que dans tous les cas, l'une est meilleure que l'autre

Cette page vous a été utile?
0 / 5 - 0 notes