Vous n'avez pas.
Mais... vous devez utiliser redux-saga :)
Dan Abramov anwser est juste à propos de la redux-thunk, mais j'en parlerai un peu plus à propos de redux-saga qui est assez semblable, mais plus puissant.
Impératif VS déclarative
-
DOM: JQuery est impératif / Réagir est déclarative
-
Les monades: IO est impératif / Gratuit est déclarative
-
Redux effets: redux-thunk est impératif / redux-saga est déclarative
Lorsque vous avez un thunk dans le vôtre mains, comme un IO monade ou une promesse, vous ne pouvez pas facilement savoir ce qu'il va faire une fois que vous exécutez. La seule façon de tester un thunk est pour l'exécuter, et se moquent de l'expéditeur (ou l'ensemble du monde extérieur, si elle interagit avec plus de trucs...).
Si vous utilisez des objets fantaisie, alors vous n'êtes pas fait de la programmation fonctionnelle.
Vu à travers le prisme d'effets secondaires, on se moque de sont un indicateur que votre code est impur, et dans le programmeur fonctionnel de l'œil, la preuve que quelque chose est faux. Au lieu de télécharger une bibliothèque pour nous aider à vérifier l'iceberg est intact, nous devrions être en naviguant autour de lui.
Un hardcore ATS/Java gars m'a demandé une fois comment vous faites moqueur en Clojure. La réponse est, nous avons l'habitude de ne pas. Nous avons l'habitude de le voir comme un signe, nous avons besoin de revoir notre code.
Source
Les sagas (comme ils l'ont obtenu mis en œuvre dans redux-saga) sont déclaratives et comme la Libre monade ou de Réagir composants, ils sont beaucoup plus faciles à tester sans se moquer.
Voir aussi cet article:
modernes de PF, il ne faut pas écrire des programmes - nous devrions écrire des descriptions de programmes, que nous pouvons ensuite l'introspection, de transformer et de les interpréter.
Confusion: actions/événements/commandes...
Il y a beaucoup de confusion dans le frontend monde sur la façon dont certains backend concepts comme CQRS / EventSourcing et de Flux / Redux peut être liée, principalement parce que dans le Flux nous utilisons le terme "action", qui peut parfois représenter à la fois du code impératif (LOAD_USER
) et des événements (USER_LOADED
). Je crois que comme événement-sourcing, vous ne devriez distribuent des événements.
À l'aide de sagas dans la pratique
Imaginez une application où il y a quelque part un lien vers un profil d'utilisateur. Le idiomatiques façon de gérer cela avec les deux middlewares serait:
redux-thunk
<div onClick={e => dispatch(actions.loadUserProfile(123)}>Robert</div>
function loadUserProfile(userId) {
return dispatch => fetch(`http://data.com/${userId}`)
.then(res => res.json())
.then(
data => dispatch({ type: 'USER_PROFILE_LOADED', data }),
err => dispatch({ type: 'USER_PROFILE_LOAD_FAILED', err })
);
}
redux-saga
<div onClick={e => dispatch({ type: 'USER_NAME_CLICKED', payload: 123 })}>Robert</div>
function* loadUserProfileSaga() {
while(true) {
const action = yield take("USER_NAME_CLICKED")
const userId = action.payload;
try {
const userProfile = yield fetch('http://data.com/${userId}')
yield put({ type: 'USER_PROFILE_LOADED', userProfile })
}
catch(err) {
yield put({ type: 'USER_PROFILE_LOAD_FAILED', err })
}
}
}
Cette saga se traduit par:
eveytime un nom d'utilisateur obtient cliqué, de récupérer le profil utilisateur, puis envoi d'un événement avec le profil chargé
Comme vous pouvez le voir, il ya certains avantages de redux-saga.
Vous gardez l'action créateurs pur (en fait, avons-nous encore besoin d'eux?)
Votre code devient beaucoup plus testable que les effets sont déclaratives
Vous pouvez introduire plus complexe de la simultanéité des contrôles à votre saga facilement, comme par exemple si l'utilisateur clique très vite sur user1 et puis, utilisateur2, nous voulons nous assurer que nous serons toujours afficher le profil de l'utilisateur2, peu importe combien de temps chacun des 2 demandes de pris. Edit: ce type de contrôle de concurrence est désormais mis en œuvre dans le haut niveau assistants takeEvery
et takeLatest
Vous n'avez pas besoin de plus pour déclencher la rpc comme des appels comme actions.loadUser()
. Votre INTERFACE utilisateur a juste besoin de l'expédition ce qui s'EST PASSÉ. Nous n'feu événements (toujours dans le passé!) et pas des actes plus. Cela signifie que vous pouvez créer découplé "canards" ou Délimitée Contextes et que la saga peut agir comme le couplage entre ces composants modulaires.
Cela signifie que votre point de vue est plus facile à gérer car ils n'ont pas besoin de plus pour contenir la couche de traduction entre ce qui a s'est vraiment passé et ce qui doit arriver comme un effet
Par exemple imaginer une infinite de défilement de la vue. CONTAINER_SCROLLED
peut entraîner NEXT_PAGE_LOADED
, mais est-ce vraiment la responsabilité de l'déroulante contenant de décider oblige à choisir entre lumière ou pas on doit charger une autre page? Ensuite, il doit être au courant de plus de choses compliquées comme les oblige à choisir entre lumière ou pas de la dernière page a été chargé avec succès ou si il existe déjà une page qui essaie de charger, ou si il n'est pas plus à gauche des éléments à charge? Je ne le pense pas: pour un maximum de réutilisabilité le défilement conteneur doit décrire qu'il a fait défiler. Le chargement d'une page est un "business" effet de défilement
Certains pourraient faire valoir que les producteurs peuvent, par nature, état cacher à l'extérieur de redux magasin avec des variables locales, mais si vous commencez à orchestrer des choses complexes à l'intérieur de thunks en commençant timers etc vous avez le même problème de toute façon. Et il y a un select
effet qui permet maintenant d'obtenir de l'état de votre Redux magasin.
Sagas peut être le temps parcouru, et permet également des complexes de flux de journalisation et de la dev-tools qui sont actuellement en cours d'élaboration. Voici quelques simples async flux de l'enregistrement qui est déjà mis en œuvre:
Le découplage
Les Sagas ne sont pas seulement le remplacement de redux thunks. Ils viennent de backend / systèmes distribués / event sourcing.
C'est une idée fausse très répandue que les sagas sont juste là pour remplacer votre redux thunks avec une meilleure testabilité. En fait c'est juste un détail d'implémentation de redux-saga. À l'aide déclarative effets est mieux que les thunks pour la testabilité, mais la saga modèle peut être mis en œuvre sur le dessus de l'impératif ou déclaratif de code.
En premier lieu, la saga est un logiciel qui permet de coordonner long de l'exécution de transactions (cohérence éventuelle), et les transactions sur les différents délimitée contextes (domain driven design jargon).
Pour simplifier ce pour frontend monde, imaginer qu'il y est widget1 et widget2. Lorsque certaines bouton sur widget1 est cliqué, il devrait avoir un effet sur widget2. Au lieu de couplage entre les 2 widgets (par ex. widget1 envoi d'une action qui cible widget2), widget1 seulement l'expédition et son bouton a été cliqué. Puis la saga écouter ce bouton, puis cliquez sur mise à jour widget2 par dispaching un nouvel événement qui widget2 est conscient.
Cela ajoute un niveau d'indirection qui est inutile pour des applications simples, mais le rendre plus facile à l'échelle des applications complexes. Vous pouvez maintenant publier widget1 et widget2 à différents mnp dépôts de sorte qu'ils n'ont jamais à se connaître les uns les autres, sans avoir à partager un registre mondial des actions. Les 2 widgets sont maintenant délimité des contextes qui peuvent vivre séparément. Ils n'ont pas besoin les uns des autres pour être compatibles et peuvent être réutilisés dans d'autres applications. La saga est le couplage entre les deux widgets que de les coordonner de manière significative pour votre entreprise.
Quelques bons articles sur la façon de structurer votre Redux application, sur lequel vous pouvez utiliser Redux-saga pour le découplage raisons:
Certains redux-saga ressources utiles