Redux Observables:对于相同的动作但不同的过滤器分开史诗?

时间:2017-03-19 03:55:37

标签: react-native redux redux-observable

我是redux observables的新手:https://github.com/redux-observable/redux-observable

我有一个简单的用例,我希望根据用户的signedIn状态做两件事。

  1. 如果已登录,请添加rsvp
  2. 如果未登录,请以模式显示
  3. 我在app/redux/epics/addRSVP.js文件中有这个:

    import 'rxjs';
    import * as scheduleActions from '../ducks/schedule';
    
    export default function searchUsers(action$, store) {
      return action$.ofType(scheduleActions.ADD_RSVP)
        .filter(() => store.getState().user.signedIn)
        .map(action => scheduleActions.rsvpAdded(action.payload));
    };
    

    我的问题是,我是否应该为签出的用例创建另一个app/redux/epics/preventRSVPIfNotSignedIn.js史诗?类似的东西:

    import 'rxjs';
    import * as authenticationActions from '../ducks/authentication';
    
    export default function searchUsers(action$, store) {
      return action$.ofType(scheduleActions.ADD_RSVP)
        .filter(() => !store.getState().user.signedIn)
        .map(action => authenticationActions.show());
    };
    

    还是有办法将两者都放在同一个文件中?如果它是前者,我觉得它最终会成为很多史诗。很高兴知道一般惯例是什么。

2 个答案:

答案 0 :(得分:4)

塞巴斯蒂安提出了很好的建议,我一般会将它们分开并复制逻辑。但是,如果你真的这么做,你可以创建自己的抽象,这样你就不需要重复了。

你可以创建一个像requireAuth这样的帮助器,它可以捕获你想要的动作,也可以创建一个只有当它们具有有效身份验证时才会接收这些动作的史诗。然后它会返回一个包裹它的新史诗。

// Helper to abstract the common auth requirement checks
// which will also dispatch authenticationActions.show()
// when they attempt to do something they can't
const requireAuth = (type, epic) => (action$, store) => {
  // matching actions which they have permission for
  const valid$ = action$
    .ofType(type)
    .filter(() => store.getState().user.signedIn);

  // matching actions they do NOT have permission for
  const invalid$ = action$
    .ofType(type)
    .filter(() => !store.getState().user.signedIn);

  return Observable.merge(
    epic(valid$, store),
    invalid$.map(action => authenticationActions.show())
  );
};

const searchUsersEpic = requireAuth(scheduleActions.ADD_RSVP, (action$, store) =>
  action$.map(action => scheduleActions.rsvpAdded(action.payload))
);

// You can then use requireAuth for any epics that require it
// as an example:
const searchMoviesEpic = requireAuth(scheduleActions.SEARCH_MOVIE, (action$, store) =>
  action$.mergeMap(action =>
    ajax(`/search/for/the/movie/${action.id}`)
      .map(resp => scheduleActions.searchMoviesFulfilled(resp))
  )
);

根据需要进行调整 - 但要小心,添加抽象可能会使您的代码库以后难以推理,或者当有人稍后调整抽象而不会意识到它如何影响其他代码路径时会引入错误。测试变得更加重要!

答案 1 :(得分:3)

如果您不确定,请始终创建单独的史诗。以后更容易测试和更改。此外,这种方法几乎没有任何缺点(性能方面)。结合两个史诗就是在不知道是否真的有必要的情况下添加抽象。

此外,通过它的外观鸭子,这两个(侧面)效果的域是不同的。我想说这是一个强有力的指标,在​​这里使用单独的史诗是一个好主意,并且将来会更加明确。

那就是说,如果你确定你的史诗不会改变或变得更复杂(目前是if / else),我想也没关系。

在第二次看之后,我猜你想要做的是"如果用户没有登录,请显示登录页面并等到他登录并成功登录后RSVP行动"。如果这是您的用例,您可能需要查看delayWhen。这可能是更好的解决方案,但它更像是RxJS的高级功能。当你对redux-observables感到更舒服时,这可能是一个很好的重构任务:)