Reputation: 13
I have the following problem with some implementation in React/Redux.
After clicking on a button, a specific redux action is call and div with notification shows on screen. You can close this notification by clicking on a (X) sign on that div (another redux action) or notification will close automatically after 5 secs. Clicking on (x) should cancell an automatic action.
actions:
const OPEN = 'show_notification';
const CLOSE = 'close_notification';
const CLOSE_AUTO = 'close_auto';
function showNotification(data) {
return {
type: 'OPEN',
data
}
}
function closeNotification(index) {
return {
type: 'CLOSE',
index
}
}
function closeAuto() {
return {
type: 'CLOSE_AUTO'
}
}
epics:
import (...)
closeNotificationAuto = action$ => action
.filter(action => action.type === OPEN)
.mergeMap(action => action
.delay(5000)
.map( () => closeAuto)
.takeUntil(action$.ofType(CLOSE))
}
Anyway, when two notifications are on screen, the action === CLOSE is closing the first one, and cancell delay() for another.
Not posting my whole code because the problem is here, in epics. Can't manage to achieve a solution:
when clicking on a (x) the specific notification is close, but another one (which time is for example 3secs) is still visible and hide automatically after another 2 secs.
Thans for any help!
Upvotes: 0
Views: 178
Reputation: 15401
The code in the epic is incomplete, so it's not totally clear (what happens inside the mergeMap?). But I did see one issue, which is that your takeUntil
is on the top-level observable chain, which means it won't just cancel that particular delay, it will also stop listening for any action at all.
Instead, you need to delay and cancel the matched action individually inside something like a mergeMap
, switchMap
, etc. This is commonly called "isolating your observer chains".
Here's what that might look like:
const closeNotificationAuto = action$ =>
action$
.ofType(OPEN)
.mergeMap(action =>
Observable.of(action)
.delay(5000)
.map(() => closeAuto())
.takeUntil(action$.ofType(CLOSE))
);
This pattern, filter then flatMap (mergeMap, switchMap, etc), is how most of your epics will look.
Regarding your comments below, it sounds like you want to add a filter to takeUntil
notifier to only take CLOSE actions that somehow uniquely identifies it.
See https://stackoverflow.com/a/48452283/1770633
const closeNotificationAuto = action$ =>
action$
.ofType(OPEN)
.mergeMap(action =>
Observable.of(action)
.delay(5000)
.map(() => closeAuto())
.takeUntil(
action$.ofType(CLOSE).filter(a => a.something === action.something)
)
);
If there isn't some sort of unique ID already available for each, you'll need to create and include one.
Upvotes: 1