One of my top reasons for using redux-saga is how testable it makes asynchronous function calls. My dilemma is that when I am programming with stateful objects that wouldn't belong inside my redux store it becomes pretty awkward programming with sagas. Is there a best practice for working with non-pure data objects and redux-saga?
Say I have callback functions I register with an API, firebase in this case, and I need to book keep these callback functions so I can unregister them later. I can't store these callback functions in redux, so does it still make sense to write this as a saga?
Seems a bit weird in one piece of code to be able to use things like put, select and in other bits of code I have to use store.dispatch.
Example:
const childAddedTrigger = (dataSnapshot: firebase.database.DataSnapshot) => {
const message = Object.assign({}, dataSnapshot.val(), {
key: dataSnapshot.key,
});
service.store.dispatch(Actions.channelMessageAdded(channelId, message));
}
service.firebase.database().ref(`channels/${channelId}/messages`)
.limitToLast(20)
.on('child_added', childAddedTrigger);
this.channelSubscriptions[channelId] = childAddedTrigger;
How do I continue to use the format of saga functions without using a redux store? What I'm saying is that you can't. You'll have to be content with using sagas to listen for the actions dispatched by your callback.
redux-thunk, GraphQL, MobX, Redux Observable, and Redux are the most popular alternatives and competitors to redux-saga.
Redux has a broader approval, being mentioned in 1036 company stacks & 832 developers stacks; compared to redux-saga, which is listed in 43 company stacks and 21 developer stacks.
First we import our Saga from the ./sagas module. Then we create a middleware using the factory function createSagaMiddleware exported by the redux-saga library. Before running our helloSaga , we must connect our middleware to the Store using applyMiddleware . Then we can use the sagaMiddleware.
You would want to use the redux-saga concept of Channels.
The effect's like take, call, put
that make async functions so easy to test with redux-saga by default interact with redux's store, because the library is first and foremost a redux middleware.
However, the eventChannel
factory function allows you to take external event sources say from a websocket or firebase and 'take' events from them, rather than take actions dispatched from the store and 'put' events to them, rather than to the redux store.
What you want is runSaga
. It is the function to run any saga by giving everything needed for a saga to work as the arguments.
As stated by @TheBrofessor, since redux-saga works by communicating with some input and output, if you can define such input and output, it is runnable in redux-saga. The channel
option and dispatch
option is responsible for providing input and output for saga. See documentation for detailed explanation.
One thing to note, which is not documented in the docs, is the behavior of stdChannel
.
Actually, the channel described in the Channel document behaves like queue.
Where as the behavior of stdChannel
is rather subscribe/dispatch (just like "channels" in any other subscription framework).
It is because stdChannel
is a special channel that is created to behave like subscription channel. In fact, when redux-saga is connected to redux store, it puts all the store's dispatch events into stdChannel
, so every saga which is take
ing all can receive the dispatched event.
You can confirm redux-saga actually defines notion of multicast
in their source code, which is implemented on the stdChannel
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With