Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Oct 22 23:30

    greenkeeper[bot] on @types

    (compare)

  • Oct 22 23:23

    greenkeeper[bot] on @types

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

  • Oct 22 22:35

    greenkeeper[bot] on @types

    (compare)

  • Oct 22 22:20

    greenkeeper[bot] on @types

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

  • Oct 22 21:28

    greenkeeper[bot] on @types

    (compare)

  • Oct 22 21:23
    greenkeeper[bot] labeled #682
  • Oct 22 21:23
    greenkeeper[bot] opened #682
  • Oct 22 21:22

    greenkeeper[bot] on @types

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

  • Oct 22 21:08

    greenkeeper[bot] on @types

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

  • Oct 21 18:10

    greenkeeper[bot] on @typescript-eslint

    chore(package): update @typescr… chore(package): update lockfile… (compare)

  • Oct 21 17:52

    greenkeeper[bot] on @typescript-eslint

    chore(package): update @typescr… chore(package): update lockfile… (compare)

  • Oct 21 17:41

    jayphelps on master

    chore(examples): Remove example… (compare)

  • Oct 21 17:41
    jayphelps closed #679
  • Oct 21 17:41

    jayphelps on master

    chore(build): add package-lock.… (compare)

  • Oct 21 17:41
    jayphelps closed #678
  • Oct 21 16:47

    greenkeeper[bot] on @types

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

  • Oct 20 16:56
    csvn commented #678
  • Oct 20 03:32
    apoorvmote commented #402
  • Oct 20 02:53
    apoorvmote commented #402
  • Oct 20 01:34
    apoorvmote commented #569
Saeed.
@StringSaeed_twitter
it turns out that axios.get() doesn't return promise, it returns object and objects can't be observable
Sung M. Kim
@dance2die

Background: A new RxJS learner (2 day on RxJS ;p & familiar with only Redux).

Is there a way to dispatch PING/PONG in basic example to fire only once even though a button is clicked multiple times? Tried wrapping it withFwithLatestFrom.

export const pingEpic = action$ => withLatestFrom(
  action$.pipe(
    ofType(PING),
    delay(1000),
    mapTo(pong()),
    tap(console.info)
  ));

I am probably looking at switchMapor exhaustMap but not sure how to apply it...

A runnable sample is here - https://codesandbox.io/s/basic-example-m5590
When you click on "PING" button, a new PING is dispatched, thus ping/ponging more as you click.
Kevin Ghadyani
@Sawtaytoes
@StringSaeed_twitter That's not the issue. From what you pasted, your switchMap is missing a return statement. You're returning undefined (mean nothing) instead of the from()......
Kevin Ghadyani
@Sawtaytoes

@dance2die I don't really understand the issue.

Right now, you're having it PING, and then 1 second later call PONG. Are you wanting PING to keep listening, but not to the onClick anymore? That's something for your React component right?

Or are you wanting something more crazy where if a PING comes in before PONG is sent, then it:

  • Restarts the timer
  • Keeps working as normal, ignoring the next PING until PONG has been sent.

Which are you wanting?

@dance2die Is this what you wanted? https://codesandbox.io/s/basic-example-kgq57
Kevin Ghadyani
@Sawtaytoes

@dance2die You need the timer observable. It's similar to the delay operator, but it is an observable creator whereas delay is a pipeline operator. That's literally the only difference.

switchMap and exhaustMap work by switching you to a new observable. The difference is that the former always switches to the new observable and kills off the old one whereas the latter only switches to a new observable once the inner one is complete.

@dance2die You don't have to use timer or switchMap. Instead, you could use takeUntil.

So you can do:

takeUntil(action$.pipe(ofType(PING))

The reason you wouldn't wanna do this is because it would kill the entire epic.

You have to have at least one inner-observable if you're going to use something like takeUntil. switchMap uses it internally so you don't have to.

Dominik Bartholdi
@imod
@Sawtaytoes how would your example look like with takeUntil? I did not quite get it...
Sung M. Kim
@dance2die
BAkqLhFxAx.gif
Thank you @Sawtaytoes. That's what I intended to do. Not with delay but with timer.
I've also played around with exhaustMap instead of switchMap, but switchMap seems more like what I wanted in this case. :)
Kevin Ghadyani
@Sawtaytoes
:thumbsup:
Kevin Ghadyani
@Sawtaytoes
@imod
// Original code
const pingEpic = (
  action$,
) => (
  action$
  .pipe(
    ofType(PING),
    delay(1000),
    map(pong),
  )
)

// Accepted solution.
const pingEpic = (
  action$,
) => (
  action$
  .pipe(
    ofType(PING),
    switchMap(() => (
      timer(1000)
    )),
    map(pong),
  )
)

// This kills the entire observable when another PING comes in. Not what you want.
const pingEpic = (
  action$,
) => (
  action$
  .pipe(
    ofType(PING),
    takeUntil(
      action$
      .pipe(
        ofType(PING)
      )
    ),
    delay(1000),
    map(pong),
  )
)

// Instead of using `switchMap`, you could use `takeUntil` and `mergeMap` just fine.
const pingEpic = (
  action$,
) => (
  action$
  .pipe(
    ofType(PING),
    mergeMap(() => (
      timer(1000)
      .pipe(
        takeUntil(
          action$
          .pipe(
            ofType(PING)
          )
        )
      )
    )),
    map(pong),
  )
)

// I use namespaces often for reusable epics and reducers (https://itnext.io/the-secret-to-using-redux-createnamespacereducer-d3fed2ccca4a)
// They comes in handy when you're using one epic for multiple uses.
const pingEpic = (
  action$,
) => (
  action$
  .pipe(
    ofType(CREATE_PING_LISTENER)
    mergeMap(({
      namespace,
    }) => (
      action$
      .pipe(
        ofType(PING),
        ofNamespace(namespace),
        takeUntil(
          action$
          .pipe(
            ofType(STOP_PING_LISTENER)
          )
        ),
        switchMap(() => (
          timer(1000)
        )),
        mapTo({ namespace }),
        map(pong),
    )),
  )
)
Sung M. Kim
@dance2die
Wow. thank you for the examples & in-line explanations
Epaphrodis
@tysepa
hello
please help me to know more about epics
Kevin Ghadyani
@Sawtaytoes
@tysepa What do you want to know?
Sung M. Kim
@dance2die
First attempt to replace thunk with redux-observable - https://codesandbox.io/s/reactts-redux-observable-basic-example-template-5ie6j
I gotta say the experience was pleasant.
How do you dispatch an action before fetching remote data to show loading indicator? (I'd like to set a prop like isPostLoading) when fetchPost action is dispatched.
Kevin Ghadyani
@Sawtaytoes
image.png
@dance2die You need to use merge or of or both to fire off 2 actions. Here's an example using your code from that CodeSandbox ^^
If anyone knows a cleaner way to write that, I'd actually like to know as well. The old version of Redux-Observable, which gave you access to dispatch, allowed this code to read a lot cleaner.
Kevin Ghadyani
@Sawtaytoes
I was thinking, if we added store.dispatch as a dependency, what would that same code look like:
image.png
Anyone know why we wouldn't wanna do this? Looks like it cleans up the code a lot too!
Dominik Bartholdi
@imod
@Sawtaytoes many thanks!
Sung M. Kim
@dance2die

Thank you @Sawtaytoes . I was trying out a different way before seeing your post.

I added the isLoading as reducer gets processed first according to documentation.

export default function postReudcer(state = [], action) {
  switch (action.type) {
    case FETCH_POST_LIST:
                                         👇
      return { ...state, isLoading: true };
    case FETCH_POST_LIST_SUCCESS:
                                                                                  👇
      return { ...state, ...action.payload, isLoading: false };
    default:
      return state;
  }
}
Let me try your version during lunch hour.
Dominik Bartholdi
@imod
@dance2die we always do it as in your example
Kevin Ghadyani
@Sawtaytoes
@dance2die I've got a good article on a bunch of common Redux-Observable use cases you can checkout here:
https://itnext.io/redux-observable-can-solve-your-state-problems-15b23a9649d7
Sung M. Kim
@dance2die
Thank you both~ 🙋‍♂️
Epaphrodis
@tysepa
@Sawtaytoes i want to know recursion of function in js
const winning = (number) => {
if(number == 1 ){
return true;
}
if(number == 4){
return false;
}
let sum = 0;
while (number> 0) {
let remain =number % 10;
let sqr = remain*remain;
sum += sqr;
number = Math.trunc(number/10);
}
return winning(sum);
};
Epaphrodis
@tysepa
And why this function winning are calling inside on it?
xavier7179
@xavier7179
@Sawtaytoes thank you! I was missing few constant that were wrongly assigned to the same text...
xavier7179
@xavier7179

In pursuit of more flexibility I wrote two epics (so they can be called separately) and found a way to call them from a third epic (when I need to run together, one after another):

export function fetchAllEpics(action$, state$) {
    return (
        action$.pipe(
            ofType(RUN_MORE_THAN_ONE_EPIC),
            mergeMap(() =>
                concat(
                    of(action_to_fire_epic_1()),
                    of(action_to_fire_epic_2()),
                    zip(
                        action$.ofType(CONSTANT_DELIVERED_BY_EPIC1_WHEN_DONE_WITH_NO_ERROR).pipe(take(1)),
                        action$.ofType(CONSTANT_DELIVERED_BY_EPIC2_WHEN_DONE_WITH_NO_ERROR).pipe(take(1))
                    ).pipe(
                        map(() =>
                            action_if_they_all_went_well()
                            )
                    )
                )
            )
        )
    );
}

While everything looks fine if they all complete without error, it looks like they broke the flow when an error is generated within one of the two epics. Any hint on what can I do better? Thank in advance!

Kevin Ghadyani
@Sawtaytoes
@xavier7179 You need a catchError in those two observables in zip.
Also you can use combine
xavier7179
@xavier7179
@Sawtaytoes I don't think I totally get your answer. With respect to the code I posted, do you mean catchError in the following pipe? And what about combine, is it to be meant as a (better) alternative to zip?
Kevin Ghadyani
@Sawtaytoes
@xgzl87 The pipes with the take(1), put catchError in each. That will fix the issue where zip fails because one of the child observables fail.
xavier7179
@xavier7179
@Sawtaytoes thanks, I did not thought about that actually... you were suggesting of using combine... do you feel like it should be done in a different way? (I mean instead of using the concat of two of and a zip [with the take] to catch them all) I still get the idea that it is not properly managed...
Kevin Ghadyani
@Sawtaytoes
You don't need two take(1) because you can put that on the zip. Also look at forkJoin and combineLaterst.
@xgzl87 ^^ you still need two catchError though. If you build a loop, then you don't need to write that code twice.
Epaphrodis
@tysepa
@xavier7179 thanks
Kevin Ghadyani
@Sawtaytoes
@xavier7179 Just realized something about what I was saying. There's a slight difference. You can use one take(1) piped off the zip, but the way it works, (unlike combineLatest) is that it keeps storing values forever until both submit. You'll be better off with combineLatest in this case. Then one take(1) is fine.
xavier7179
@xavier7179

@Sawtaytoes Fist of all I would like to thank you because I got an improved code, also in comprehension, such as:

export function fetchAllEpics(action$, state$) {
    return (
        action$.pipe(
            ofType(RUN_MORE_THAN_ONE_EPIC),
            mergeMap(() =>
                concat(
                    of(action_to_fire_epic_1()),
                    of(action_to_fire_epic_2()),
                    concatLates([
                        action$.ofType(CONSTANT_DELIVERED_BY_EPIC1_WHEN_DONE_WITH_NO_ERROR),
                        action$.ofType(CONSTANT_DELIVERED_BY_EPIC2_WHEN_DONE_WITH_NO_ERROR)
                    ]   
                    ).pipe(
                        map(([response_EPIC1, response_EPIC2]) => action_if_they_all_went_well()),
                        catchError(([error_EPIC1, error_EPIC2])) => action_if_something_got_wront())
                    )
                )
            )
        )
    );
}

Now, let's suppose for the sake of simplicity that my two actions perform some ajax call, if one of them fails (e.g. the url is not correct), the overall epic does not brake but the catchError is never called.... Did I miss something?

Kevin Ghadyani
@Sawtaytoes
@xavier7179 The catchError should be called in that case. If you're code's different than this, make sure the concat observable isn't failing.