This question may be about redux-observable
or rxjs
or both.
I'm looking for a way to start, stop or resume an epic through specific actions. For example, the epic (that's already part of the epic middelware) will be active when the action {type: 'START'}
is received but will be inactive when the action {type: 'END'}
is received. Is this possible?
The concept of an epic is the core part of Redux-Observable. An epic is a function that takes a stream of actions and returns a stream of actions. All of the dispatched actions go into the action stream.
REMEMBER: Epics run alongside the normal Redux dispatch channel, after the reducers have already received them. When you map an action to another one, you are not preventing the original action from reaching the reducers; that action has already been through them! The real power comes when you need to do something asynchronous.
Remember, Epics take a stream of actions in and return a stream of actions out. If the RxJS operators and behavior shown so far is unfamiliar to you, you'll definitely want to take some time to dive deeper into RxJS before proceeding. You can then update your Store's state in response to that FETCH_USER_FULFILLED action:
That way you can remain productive and learn RxJS as you go. redux-thunk is much simpler to learn and use, but that also means it's far less powerful. Of course, if you already love Rx like we do, you will probably use it for everything! An Epic is the core primitive of redux-observable.
You could use a combination of switchMap
and filter
to do this (assuming that all actions incl. the start/end-actions come from the same source)
If you start/end-actions are coming from a seperate source it is even easier, then you can skip the step of separating the source-stream.
Run the code-example below to see it in action.
// this would be your source
const actions$ = new Rx.Subject();
// in this example controllActions and dataActions are derived from the same stream,
// if you have the chance to use 2 seperate channels from the start, do that
const controllActions$ = actions$
.filter(action => action.type === "END" || action.type === "START");
const dataActions$ = actions$
.filter(action => action.type !== "END" && action.type !== "START");
const epic$ = controllActions$
.switchMap(action => {
if (action.type === "END") {
console.info("Pausing stream");
return Rx.Observable.never();
} else {
console.info("Starting/Resuming stream");
return dataActions$;
}
});
epic$.subscribe(console.log);
// simulating some action emissions, the code below is _not_ relevant for the actual implementation
Rx.Observable.from([
"Some data, that will not be emitted...",
{type: "START"},
"Some data, that _will_ be emitted...",
"Some more data, that _will_ be emitted...",
{type: "END"},
"Some data, that will not be emitted...",
"Some data, that will not be emitted...",
{type: "START"},
"Some data, that _will_ be emitted...",
"Some more data, that _will_ be emitted..."
])
.concatMap(d => Rx.Observable.of(d).delay(400))
.subscribe(actions$);
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>
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