Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 12:32
    hitmands edited #539
  • 12:30
    hitmands synchronize #539
  • 12:19
    hitmands synchronize #539
  • 12:18
    hitmands synchronize #539
  • 12:18
    hitmands synchronize #539
  • 12:17
    hitmands synchronize #539
  • 12:16
    hitmands synchronize #539
  • 12:13
    hitmands synchronize #539
  • 12:11
    hitmands synchronize #539
  • 12:10
    hitmands commented #539
  • 12:07
    hitmands synchronize #539
  • 11:36
    hitmands commented #539
  • 11:36
    hitmands commented #539
  • Dec 10 20:19

    greenkeeper[bot] on @types

    (compare)

  • Dec 10 20:05

    greenkeeper[bot] on @types

    chore(package): update @types/n… chore(package): update lockfile… (compare)

  • Dec 10 19:28
    greenkeeper[bot] commented #698
  • Dec 10 19:28

    greenkeeper[bot] on @types

    chore(package): update @types/c… chore(package): update lockfile… (compare)

  • Dec 10 06:48
    Sawtaytoes commented #674
  • Dec 09 21:38

    greenkeeper[bot] on @types

    (compare)

  • Dec 09 21:30

    greenkeeper[bot] on @types

    chore(package): update @types/n… chore(package): update lockfile… (compare)

Jim Rhodes
@jimjiminyjimjam_twitter
@Sawtaytoes - yep that’s exactly it. So the only thing I think I’m now struggling with is the takeuntil? As I have multiple actions all the same type - The only way I’m distinguishing them by is device id. What would you suggest I use takeuntil with?
Kevin Ghadyani
@Sawtaytoes

@jimjiminyjimjam_twitter The issue here is that you're creating more listeners every time a task comes in and never getting rid of them. So basically, when a task is listed as "complete" for that device ID, then you should kill off that inner TASK_COMPLETE observable and stop listening to action$ on it.

Actually, with what you have, a simple take(1) would suffice. Normally I use takeUntil because I kill a listener on complete, but in your case, you're wanting to execute something else on complete so it's a bit different. Using take(1) will say, if a single TASK_COMPLETE comes in after the filter, then it's safe to end this observable when it's done processing.

Kevin Ghadyani
@Sawtaytoes

@jimjiminyjimjam_twitter

const taskNextInQueue$ = (action$, state$) =>
  action$.pipe(
    ofType(TASK_SEND),
    mergeMap(action => {
      return action$.ofType(TASK_COMPLETE).pipe(
        filter(action2 => action2.deviceId == action.deviceId),
        take(1), // PUT IT HERE
        switchMap(action => {

Based on your code, I'm assuming you're going to execute more tasks with switchMap. You might consider instead using map and pushing through another TASK_SEND action. Once you add that switchMap, the take(1) might not work like you think. Add a finalize operator to log a string when the inner TASK_COMPLETE observable completes to see if that's working properly.

Sung M. Kim
@dance2die
Ah I forgot about this channel and ended up creating an redux-observable/redux-observable#695 😅.
Would "this link in warning" shows 404 in this channel be fine?
Kevin Ghadyani
@Sawtaytoes
@dance2die I don't understand what you're saying, but making an issue on GitHub is fine. As far as I know, @jayphelps doesn't frequent this chat.
Sung M. Kim
@dance2die
Thanks @Sawtaytoes. I misunderstood why creating an issue could have had been a problem.
(must've have mixed it up with other communities' guidelines).
Nisim Joseph
@nisimjoseph

Hi, I encounter an issue with Epic.ts file which limits the Generic use of Output Action to extends Input. why is that?
My Output action doesn't need to extend the Input action and it quite limits the development.
https://github.com/redux-observable/redux-observable/blob/master/src/epic.ts

When I change the generic Output to extends Action it gives me more flexability.

xavier7179
@xavier7179
May I ask a general question that I'm not so sure it is covered (I read a lot online, including a great @Sawtaytoes post covering a lot of redux-observable examples)? Is there a nice and clean way to make an epic managing an ajax request to ignore any OF_STARTING_TYPE_ACTION while the actual request is not ended, in order to ensure only one ajax request per time is served?
Kevin Ghadyani
@Sawtaytoes
@xavier7179 That's actually more of an RxJS question :P. exhaustMap is what you want.
popoleeMaster
@popoleeMaster
Hello
Is there someone that could help me for a little problem I have ?
Kevin Ghadyani
@Sawtaytoes
@popoleeMaster Yes.
popoleeMaster
@popoleeMaster
THanks
I have the following code :
const goToItemEpic = (action$, state$): Observable<any> => action$.pipe(
    ofType(ItemsDetailsActions.goToItem),
    concatMap((action: {payload: {projectId: string; datastoreId: string; itemId: string}}) => {
        const projectId = ProjectSelectors.getCurrentProjectId(state$.value);
        if(action.payload.projectId !== projectId) {
            return of(ProjectActions.setCurrentProjectId({projectId: action.payload.projectId})).pipe(
                delay(1000),
                switchMap(() => {
                    return [
                        DatastoreActions.setCurrentDatastoreId({datastoreId: action.payload.datastoreId}),
                        ItemsActions.setCurrentItemId({ itemId: action.payload.itemId })
                    ];
                })
            )
        } else {
            return [
                DatastoreActions.setCurrentDatastoreId({datastoreId: action.payload.datastoreId}),
                ItemsActions.setCurrentItemId({ itemId: action.payload.itemId })
            ];
        }
    })
);
Basically, if(action.payload.projectId !== projectId) I would like to set the current project, and then after a delay (that I wish it to be another observable) I also dispatch 2 actions. But i can't manage to do it, maybe you can help @Sawtaytoes
like, setCurrentProjectId dispatch a series of action, the last beeing getDatastoresSuccess. I would like that after getDatastoresSuccess is executed, setCurrentDatastoreId, setCurrentItemId are dispatched
is it possible to do ?
Evert Bouw
@evertbouw
sure
return merge(
    of(ProjectActions.setCurrentProjectId({projectId: action.payload.projectId})),
    of(
        DatastoreActions.setCurrentDatastoreId({datastoreId: action.payload.datastoreId}),
        ItemsActions.setCurrentItemId({ itemId: action.payload.itemId })
    ).pipe(
        delay(1000)
    )
)
which is basically the same as using startWith but that might not read clearly in this case
return of(
    DatastoreActions.setCurrentDatastoreId({datastoreId: action.payload.datastoreId}),
    ItemsActions.setCurrentItemId({ itemId: action.payload.itemId })
).pipe(
    delay(1000),
    startWith(ProjectActions.setCurrentProjectId({projectId: action.payload.projectId}))
)
ImmortaL
@ImmRanneft
Guys, I don't know if you know someone who maintains redux-observable.js.org, but the example for "using react" is not working :) Not really dev-friendly to start with it.
Kevin Ghadyani
@Sawtaytoes
@ImmRanneft Could you link to it?
Either @evertbouw or @jayphelps or both are in charge of that site.
Evert Bouw
@evertbouw
I think the source for the docs have been updated, will need to regenerate the website
by updated I mean the examples have been removed
Evert Bouw
@evertbouw
ImmortaL
@ImmRanneft
:) Now it's not that disappointing, thank you
Kevin Mui
@kmui2
Hello, I'm guessing this might be the place to ping for help. I've recently been trying out redux-observable after using other patterns in thunks and sagas. Here's my question: https://stackoverflow.com/q/59187250/8109319.
Kevin Ghadyani
@Sawtaytoes
@kmui2 Are you still needing help? Looks like someone's already answered your question on StackOverflow. Main thing to note is you always setup an action$ listener before dispatching an action otherwise, you won't see it.
Kevin Ghadyani
@Sawtaytoes

@kmui2 I was going to edit the other StackOverflow answer, but didn't understand what the answerer was going for so I wrote my own response instead.

I wrote an article here about splitting observable pipelines to allow multiple actions to "fall through" and get automatically dispatched here: https://itnext.io/redux-observable-can-solve-your-state-problems-15b23a9649d7

What you're talking about is pretty standard for when I use Redux-Observable, but the confusion you had where pauseGame wasn't firing makes complete sense. In that case, I wrote a separate article about using dispatch anywhere in your pipeline instead of having the actions "fall through" and become automatically dispatched: https://dev.to/sawtaytoes/the-best-practice-anti-pattern-jj6

Evert Bouw
@evertbouw

@Sawtaytoes your example can be a bit simplified by using startWith, and with my preferred formatting it's only a tab depth of 3

const fetchUserEpic = action$ => action$.pipe(
    ofType(FETCH_USER),
    switchMap(({ username, password }) => ajax.getJSON("https://api.example.com/login").pipe(
        startWith(setLoading("login")),
        switchMap(({ authToken }) => of(
            fetchUserSucceeded(authToken),
            setLoaded("login"))
        ),
        catchError(error => of(fetchUserFailed(error))),
    )),
);

prettier makes this slightly worse with one more indent

Evert Bouw
@evertbouw
the inner switchMap should probably be mergeMap (flatMap) since there is nothing to cancel
or better yet use endWith, saves another tab level
const fetchUserEpic = action$ => action$.pipe(
    ofType(FETCH_USER),
    switchMap(({ username, password }) => ajax.getJSON("https://api.example.com/login").pipe(
        startWith(setLoading("login")),
        map(fetchUserSucceeded(authToken)),
        endWith(setLoaded("login"))
        mapError(fetchUserFailed),
    )),
);
Kevin Mui
@kmui2
@Sawtaytoes
Thanks for the help! Will take a look at this later
Didn't get a chance yet to try out your solution
Kevin Ghadyani
@Sawtaytoes

@kmui2 :thumbsup:

@evertbouw The endsWith part is really smart. I'll use that going forward. The startWith won't work though unless it's under the map. Really great idea as well though.

const fetchUserEpic = action$ => (
  action$
  .pipe(
    ofType(FETCH_USER),
    switchMap(({ username, password }) => (
      ajax
      .getJSON("https://api.example.com/login")
      .pipe(
        map(fetchUserSucceeded(authToken)),
        startWith(setLoading("login")),
        endWith(setLoaded("login")),
        catchError(() => of(fetchUserFailed())),
      )
    )),
  )
)

^^ Like that right?

Kevin Ghadyani
@Sawtaytoes

@evertbouw I think this is a fantastic workaround for splitting pipelines.

My one concern is we lose sequential pipeline execution. You have to look at available operators and ensure you're checking for any startWith to figure out what's getting executed when.

This opens up a whole new world for me. I wish someone'd pointed this out sooner. Did you just come up with it?

Kevin Ghadyani
@Sawtaytoes

@evertbouw There's one other issue. Looking at that code, if you do endWith(state$.value), you'll get the old state. So you'll need finalize instead.

Also, say you do care about the final computed value for some reason, then you'd need to concatMap to an array of actions.

Evert Bouw
@evertbouw
endWith is a fairly new operator I'm not sure if I've used it
I do use startWith a bunch, which is practically the same as doing concat with two observables
Kevin Ghadyani
@Sawtaytoes

@evertbouw I went ahead and added your info to my answer:
https://stackoverflow.com/questions/59187250/how-can-i-dispatch-one-action-wait-1-second-then-dispatch-two-more-actions-in#

Works for this particular use case.

@kmui2 I updated my answer with another suggestion. This way, you can choose the one you like best or that works best for your situation.
Kevin Ghadyani
@Sawtaytoes
I was wrong about using finalize. It just gets called when the observable completes. Unlike endWith, it doesn't pass value down the chain. That's a problem. I guess you could always concatMap to an array of actions instead.
Evert Bouw
@evertbouw
tbh FETCH_USER is enough of a signal to set the loading state, and the success/error to end it. So you can do without startWith/endWith usually
unless you are filtering before the switchmap
Kevin Ghadyani
@Sawtaytoes

Published an article on this same topic we've been discussing:
https://itnext.io/redux-observable-code-that-fixes-everything-b7832b904b6b

Hopefully this helps everyone else who's been having this issue.

Seems like it's a problem I see often in this channel.