At , we are heavy users of in our web and mobile apps. After first using and middleware, we are now happily using as our way to deal with asynchronous operations. If you are not using yet in your React apps, you should drop what you’re doing and read the tutorial! Meeshkan [redux](http://redux.js.org/) [redux-promise](https://www.npmjs.com/package/redux-promise) [redux-thunk](https://github.com/gaearon/redux-thunk) [redux-saga](https://github.com/redux-saga/redux-saga) [redux-saga](https://github.com/redux-saga/redux-saga) The is a great way to describe side effects through pure functions. There are many different ways to understand the pattern, but in my own mind, I like to think of it as a script. Take, for example, the saga: Saga Pattern import { call, put } from 'redux-saga/effects';import fetchKittenPictures from './kittens'; function* fetchKittenPicturesSaga(action) {try {yield put({ type: 'FETCH_KITTEN_EXECUTING' });const critters = yield call(fetchKittenPictures);yield put({ type: 'FETCH_KITTEN_SUCCESS', payload: critters });} catch(e) {yield put({ type: 'FETCH_KItTEN_FAILURE' });}} Giving this script to an actor that will declaim my saga, she will triumphantly pronounce: KITTEN FETCH (a play in one act) Teller: I am executing a kitten fetch!Teller: I am making a call to my kitten fetch api![she goes offstage, comes back]Teller: I have my kittens.[in the event that she breaks her leg, she yells "NO KITTENS!"] But what if we gave our saga to the late great Robin Williams. Would he follow our script? No! It may look something like this: KITTEN FETCH (a play in one act) Robin: I am executing a kitten fetch!Robin: Wait, kittens don't fetch, dogs fetch. And why are we executing kittens? That's cruel.[pauses for laughter]Robin: Ah, we're talking about an API. I could sure use an IPA![pauses for laughter]Robin: I am making a call to my kitten fetch api![he goes offstage, comes back]Robin: I have my kittens.[in the event that he breaks his leg, he yells "NO KITTENS!"] A different teller will tell the saga differently. In the world of React development, where sagas contain core business logic, sometimes sagas need to change slightly depending on the platform on which they’re running. For example, we may need two “tellers” for the same saga — one for web and one for mobile. They need to be able to share most of their “script” while making slight adjustments based on their unique way of telling the saga. An anti-pattern would be to hardcode into a saga all of the different ways it could be told. The cleaner solution is to give the saga to a teller and have her tell it. So, we have put together a hack called that does exactly this. The API is dead simple: saga-teller function sagaTeller(saga, rules); The first argument, , is the saga that the teller will tell, and is a blueprint for how the teller will modify the saga. saga rules The rules object itself is in the form: // match// note that put and call should be mutually exclusive {when: <'before' or 'after'>,put: <an action if we are responding to PUT>,call: <a function if we are responding to CALL>,effect: <any valid redux-saga effect like all, put, take...>} // rules{first: <call or put>,matches: <Array of match>,last: <call or put>} Using our kitten saga, we may do this: const myVeryOwnFetchKittenSaga(fetchKittenSaga, {first: call(lookMomIKnowHowToUseSagas),matches: [{when: 'after',put: 'FETCH_KITTEN_EXECUTING'effect: put({type:'MOM_YOU_SHOULD_BE_MORE_PROUD_OF_ME'}),},],}); And there you have it. Now, when I tell the saga, the first will do is call a function telling my mom that I know how to use sagas. Then, the chugs along, and after it emits a action with , it sends out a action. This way, the original saga stays intact and my personal saga can be used wherever I want. This is also really easy to test—you just need to assert that the rules object contains the correct logic. react-saga fetchKittenSaga put FETCH_KITTEN_EXECUTING MOM_YOU_SHOULD_BE_PROUD_OF_ME In a more real-world example, this allows you to write one saga and then write a few rules that tweak its behavior based on if you are web or mobile, Android or iOS, etc. Note that the pattern is a strategy. You should never drive your app down the field with it. Think of it as a sort of patch for your saga — it should represent the minimum amount of work needed to modify a core saga, but anytime the teller’s version dwarfs the saga itself, it becomes an unwieldy kludge. In this case, just write (and test) two different sagas. saga-teller goal line Below is a gist that shows a rudimentary implementation of a . The function at the bottom just allows you to chain together multiple tellers, so you can do . Think of this like the telephone game, where each teller hears the version of the previous one and modifies it with their special addition. saga-teller tell tell(mySaga).by(teller0, teller1, teller2) I will definitely not be making anything other than a gist for this because it is based on a internal API and is really fragile in case of updates. But it is short enough that you can copy it, paste it, and modify it to your heart’s content. We’ve been using a version of it at with lots of success. Enjoy telling your sagas! redux-saga Meeshkan