ReduxObservable cancellation based on action type and its data

我的梦境 提交于 2019-12-11 16:54:47

问题


I have React app which uses redux-observable with typescript. In this scenario, FetchAttribute Action gets triggered with a id and then make an ajax call. In certain case, I would want to cancel the ajax request if "FETCH_ATTRIBUTE_CANCEL" action was triggered with the same id as of "FetchAttributeAction" action.

action$.ofType(FETCH_ATTRIBUTE)
    .switchMap((request: FetchAttributeAction) => {

      return ajax.getJSON(`/api/fetch-attribute?id=${request.id}`)
        .flatMap((fetchUrl) => {
            // return new action
        })
        .takeUntil(action$.ofType(FETCH_ATTRIBUTE_CANCEL));
    });

interface FetchAttributeAction{
  id: number;
}

Problem: How do we cancel the execution based on action type + action data? In my case, it would FETCH_ATTRIBUTE_CANCEL and id.


回答1:


The key is to filter actions in the takeUntil notifier to only those which match the ID you care about.

action$.ofType(FETCH_ATTRIBUTE_CANCEL).filter(action => action.id === request.id)

So here's what it might look like:

Demo: https://stackblitz.com/edit/redux-observable-playground-xztkoo?file=fetchAttribute.js

const fetchAttributeEpic = action$ =>
  action$.ofType(FETCH_ATTRIBUTE)
    .mergeMap(request =>
      ajax.getJSON(`/api/fetch-attribute?id=${request.id}`)
        .map(response => fetchAttributeFulfilled(response))
        .takeUntil(
          action$.ofType(FETCH_ATTRIBUTE_CANCEL).filter(action => action.id === request.id)
        )
    );

You can also take a look at previous questions:

  • Redux Observable: If the same action is dispatched multiple times, how do I cancel one of them?
  • Independent chain cancellation in redux-observable?
  • Dispatch an action in response to cancellation

The OP also pointed out that they were using switchMap (as did I originally when I copied their code) which would have meant that the epic only ever had one getJSON at a time since switchMap will unsubscribe from previous inner Observables. So that also needed to be chained. Good catch!




回答2:


I think you should be able to make takeUntil selective for a certain action id with pluck and filter.

ex:

.takeUntil(action%.ofType(FETCH_ATTRIBUTE_CANCEL)
.pluck('id')
.filter((cancelActionID) => cancelActionID === fetchID))

The non-obvious part to me is how to get the current fetchID to run that comparison. I might consider try using do to store in a temporary variable



来源:https://stackoverflow.com/questions/48447351/reduxobservable-cancellation-based-on-action-type-and-its-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!