Quelle est la meilleure pratique pour dériver des données dans componentDidUpdate , en les poussant dans le magasin redux, mais aussi en utilisant ces données pour dériver davantage de données, et à nouveau les pousser dans le magasin redux? Étant donné que le redux est synchrone, j'espérais pouvoir accéder au magasin mis à jour juste après avoir effectué l'envoi, mais je suppose que, comme il est toujours dans le composant mapStateToProps . c'est-à-dire que j'ai essayé -
componentDidUpdate(){
const a = this.determineA()
this.storeA(a);
this.doSomethingElse(a) // using a local copy of A
}
this.props.A est encore l'ancienne valeur
devrais-je être quelque chose de plus comme -
componentDidUpdate(){
this.determineAndStoreA()
this.doSomethingElse(this.props.A) // hoping this would be the updated A
}
Avec quelques recherches supplémentaires, j'ai trouvé une question similaire dans https://github.com/reduxjs/react-redux/issues/291 . Dan recommande de réagir à l'action dans le réducteur, mais c'est comme si je devais maintenant combiner la logique de détermination de A, de détermination de B à partir de A, de stockage de A et de B en même temps?
3 Réponses :
Vous n'obtiendrez pas l'accessoire mis à jour dans le même cycle que Redux envoie la valeur dans le magasin et déclenche une autre mise à jour du composant.
Avez-vous vraiment besoin de déclencher les deux actions à partir de componentDidUpdate?
Ce que vous pouvez faire est de créer une nouvelle action qui est déclenchée à partir de l'action où vous avez stocké votre valeur A.
quelque chose comme ça
store.dispatch(saveValueA()).then(() => doSomeAction() );
Votre composant sera renvoyé chaque fois que A changerait, et componentDidUpdate sera appelé.
Vous pouvez alors faire quelque chose comme:
componentDidUpdate(prevProps){
const hasAChanged = this.props.A !=== prevprops.A;
if (hasAChanged) {
this.determineAndStoreA()
} else {
this.doSomethingElse(this.props.A)
}
}
Je ne suis pas sûr de ce que vous essayez de faire, j'espère que cela vous aidera.
Je pense que je vois avec quoi vous luttez. Laissez-moi d'abord essayer de décrire plus en détail le scénario auquel je pense que vous êtes confronté.
Vous avez A et B dans votre boutique. C est dérivé de A et B , donc si A change, vous voulez dériver C et placez-le dans votre boutique. Vous pourriez alors avoir le composant prop E qui est dérivé de C et D . L'action x change A et vous avez maintenant besoin de la nouvelle valeur pour C ou E et il est difficile de le faire en une seule étape sans rendre les réducteurs trop compliqués.
J'ai utilisé trois approches principales pour des scénarios comme celui-ci et celle que je recommanderais dépend des spécificités du scénario. Ce ne sont que des approches différentes pour savoir comment / quand / où déterminer C (et pourraient être étendues à d'autres dérivations comme E ).
Approche 1
Calculez C dans un middleware conçu pour gérer les effets secondaires des actions.
C'est l'approche la plus similaire à celle que vous avez déjà. Il le déplace simplement hors d'un composant afin que vous ne luttiez pas contre l'interaction entre votre magasin et lorsque les méthodes de cycle de vie reçoivent les nouvelles informations. Pour cette approche, j'utiliserais Redux Saga et le ferais gérer le calcul de C en réponse à l'action x et l'envoi de l'action pour mettre à jour le magasin avec la nouvelle valeur pour C . C'est facile à faire (si vous avez dépassé la courbe d'apprentissage initiale de Redux Saga) puisque Redux Saga reçoit l'action une fois que le magasin a déjà été mis à jour. Le principal inconvénient de cette approche est que votre boutique sera temporairement dans un état incohérent où C ne reflète pas encore le changement en A . Pour certains scénarios, cela compte et pour certains non. L'autre inconvénient potentiel est que si vous n'utilisez pas déjà Redux Saga, cela peut être un peu intimidant au début car l'utilisation des fonctions du générateur et du rendement et l'ensemble de l'état d'esprit lors de l'utilisation de Redux Saga peuvent ressentir un peu extraterrestre (mais j'aime vraiment utiliser Redux Saga pour des scénarios asynchrones complexes).
Approche 2 Calculez C dans un créateur d'action.
Cela implique généralement d'utiliser un thunk pour la réponse initiale à l'action x et le thunk peut alors obtenir B à partir du magasin, calculer C et distribuer une action avec une charge utile qui contient deux éléments - l'un utilisé par le réducteur pour A et l'autre utilisé par le réducteur pour C . Le principal inconvénient de cette approche est que s'il existe plusieurs façons dont les dépendances pour C (c'est-à-dire A et B ) peuvent changer, cela peut devenir une manière compliquée d'organiser les choses, mais pour certains scénarios, cela peut fonctionner correctement. Je me suis principalement éloigné de cette approche au profit des deux autres approches.
Approche 3 Ne mettez pas C dans votre boutique.
Si C est entièrement dérivé d'autres éléments de votre boutique, alors il n'a pas vraiment besoin d'être dans la boutique. C est juste une vue sur d'autres informations dans votre magasin. Vous pouvez utiliser un sélecteur à cette fin à la place. S'il est coûteux de dériver C , utilisez un sélecteur mémorisé. Dans le cas plus compliqué d'avoir également E qui est dérivé de C et D , un sélecteur pour E peut tirez parti du sélecteur pour C tout en obtenant D depuis le magasin. C'est l'approche que je préfère généralement à moins qu'il n'y ait une raison impérieuse pour que C soit dans le magasin. Cette approche permet à vos réducteurs de rester simples et indépendants tout en gardant votre magasin dans un état cohérent.
Autres approches
Il existe d'autres façons de faire cela, mais les 3 approches ci-dessus sont celles que j'ai moi-même utilisées. Une autre voie consiste à avoir un réducteur qui exploite d'autres réducteurs. Dans cette approche, les réducteurs pour A et B seraient utilisés par un réducteur qui calcule ensuite C et retourne l'état avec les trois informations . Il existe des packages pour faciliter la composition de réducteurs de cette manière, mais je ne les ai pas utilisés car je ne suis pas très intéressé par cette approche. Pour moi, je ne me sens pas au bon endroit pour mettre cette complexité.
Il serait utile d'en savoir plus sur ce que vous faites dans
determineA. Toute cette configuration ressemble à une odeur de code. Il semble que l'action qui a provoqué cette mise à jour n'a été que partiellement gérée par votre réducteur et que votre composant effectue maintenant une autre étape du travail et la distribue à vos réducteurs. Je voudrais voir si vous pouvez demander à vos réducteurs de s'occuper entièrement de cela en une seule étape plutôt que de déléguer une partie du travail à un composant.c'est un commentaire juste, j'ai ajouté un peu plus à ma question. Je pense que vous pourriez avoir raison, je vais prendre un autre passage et voir si la logique peut être combinée et gérée dans une action / réducteur de redux