Reputation: 2517
How would I do the following in a single epic
The following dispatches the last two actions but not pauseGame().
const moveEpic: RootEpic = (action$, state$) =>
action$.pipe(
filter(isActionOf(move)),
map(() => pauseGame()),
filter(() => state$.value.ruleRow.lastMoveSuccessful),
delay(1000),
switchMap(() => [
removeBoardObject(
state$.value.ruleRow.totalMoveHistory[state$.value.ruleRow.totalMoveHistory.length - 1]
.dragged,
),
resumeGame(),
]),
);
Upvotes: 1
Views: 518
Reputation: 7297
The reason pauseGame
isn't dispatching is because you're not dispatching it. You're calling the action creator and then immediately changing your observable state to lastMoveSuccessful
.
Instead, what you want is to split the pipeline and merge
them back to one. I know this is confusing, but it's how Redux-Observable works at the moment. If you want a different way where you can dispatch at any point in time, checkout my article: https://dev.to/sawtaytoes/the-best-practice-anti-pattern-jj6
When the move
type occurs, switch to a new observable. That observable is a merging of 2 new observables: one which immediately dispatches pauseGame
, the other which checks if the last move was successful, and if so, waits a second and dispatches 2 other actions.
const moveEpic: RootEpic = (action$, state$) => (
action$.pipe(
filter(isActionOf(move)),
switchMap(() => (
merge(
of(pauseGame()),
of(state$.value.ruleRow.lastMoveSuccessful).pipe(
filter(Boolean),
delay(1000),
concatMap(() => [
removeBoardObject(
state$.value.ruleRow.totalMoveHistory[
state$.value.ruleRow.totalMoveHistory.length - 1
].dragged
),
resumeGame(),
]),
)
)
)),
);
)
As a side note, I don't know why you've created your own isActionOf
function, but normally you should be able to change that line to ofType(move)
instead.
Evert Bouw provided a simpler suggestion utilizing startWith
and endWith
. You'll lose sequential ordering in your pipeline, but you don't have to split it:
const moveEpic: RootEpic = (action$, state$) => (
action$.pipe(
filter(isActionOf(move)),
switchMap(() => (
of(state$.value.ruleRow.lastMoveSuccessful).pipe(
filter(Boolean),
delay(1000),
map(() => (
removeBoardObject(
state$.value.ruleRow.totalMoveHistory[
state$.value.ruleRow.totalMoveHistory.length - 1
].dragged
)),
startWith(pauseGame()),
endWith(resumeGame()),
)
)
)),
);
)
Keep in mind, if you needed to know the value of state$
in endWith
, you'd want to use finalize
instead. It takes a function instead of a value.
Upvotes: 2